xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision eee23b56e1e3dc601a475ae8105a240b0658f698)
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>
4674ae819SStefano Zampini #include <petscblaslapack.h>
5daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
6674ae819SStefano Zampini 
71e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*);
81e0482f5SStefano Zampini 
9a13144ffSStefano Zampini /* returns B s.t. range(B) _|_ range(A) */
10a13144ffSStefano Zampini #undef __FUNCT__
11a13144ffSStefano Zampini #define __FUNCT__ "MatDense_OrthogonalComplement"
12a13144ffSStefano Zampini PetscErrorCode MatDense_OrthogonalComplement(Mat A, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
13a13144ffSStefano Zampini {
14a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
15a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
16a13144ffSStefano Zampini   PetscReal      *sing;
17a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
18a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
19a13144ffSStefano Zampini   PetscErrorCode ierr;
20a13144ffSStefano Zampini 
21a13144ffSStefano Zampini   PetscFunctionBegin;
22a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
23a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
24a13144ffSStefano Zampini #endif
25a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
26a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
27a13144ffSStefano Zampini 
28a13144ffSStefano Zampini   /* workspace */
29a13144ffSStefano Zampini   if (!work) {
30a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
31f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
32a13144ffSStefano Zampini   } else {
33a13144ffSStefano Zampini     ulw   = lw;
34a13144ffSStefano Zampini     uwork = work;
35a13144ffSStefano Zampini   }
36a13144ffSStefano Zampini   n = PetscMin(nr,nc);
37a13144ffSStefano Zampini   if (!rwork) {
38a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
39a13144ffSStefano Zampini   } else {
40a13144ffSStefano Zampini     sing = rwork;
41a13144ffSStefano Zampini   }
42a13144ffSStefano Zampini 
43a13144ffSStefano Zampini   /* SVD */
44a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
45a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
46a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
47a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
51a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
52a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
53a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
54a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
55a13144ffSStefano Zampini   if (!rwork) {
56a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
57a13144ffSStefano Zampini   }
58a13144ffSStefano Zampini   if (!work) {
59a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
60a13144ffSStefano Zampini   }
61a13144ffSStefano Zampini   /* create B */
62a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
63a13144ffSStefano Zampini   ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
64a13144ffSStefano Zampini   ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
65a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
66a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
67a13144ffSStefano Zampini #else
68a13144ffSStefano Zampini   PetscFunctionBegin;
69a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
70a13144ffSStefano Zampini #endif
71a13144ffSStefano Zampini   PetscFunctionReturn(0);
72a13144ffSStefano Zampini }
73a13144ffSStefano Zampini 
741e0482f5SStefano Zampini /* TODO REMOVE */
751e0482f5SStefano Zampini #if defined(PRINT_GDET)
761e0482f5SStefano Zampini static int inc = 0;
771e0482f5SStefano Zampini static int lev = 0;
781e0482f5SStefano Zampini #endif
791e0482f5SStefano Zampini 
80a13144ffSStefano Zampini #undef __FUNCT__
81a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCComputeNedelecChangeEdge"
821e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
83a13144ffSStefano Zampini {
84a13144ffSStefano Zampini   PetscErrorCode ierr;
85a13144ffSStefano Zampini   Mat            GE,GEd;
86a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
87a13144ffSStefano Zampini   PetscScalar    *ptr;
88a13144ffSStefano Zampini 
89a13144ffSStefano Zampini   PetscFunctionBegin;
90a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
91c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
92a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
93a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
94a13144ffSStefano Zampini 
95a13144ffSStefano Zampini   /* gradients */
96a13144ffSStefano Zampini   ptr  = work + 5*esize;
97a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
98a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
99a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
100a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
101a13144ffSStefano Zampini 
102a13144ffSStefano Zampini   /* constants */
103a13144ffSStefano Zampini   ptr += rsize*csize;
104a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
105a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDense_OrthogonalComplement(GEd,5*esize,work,rwork,GKins);CHKERRQ(ierr);
109a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1101e0482f5SStefano Zampini 
1111e0482f5SStefano Zampini   if (corners) {
1121e0482f5SStefano Zampini     Mat            GEc;
1131e0482f5SStefano Zampini     PetscScalar    *vals,v;
1141e0482f5SStefano Zampini 
1151e0482f5SStefano Zampini     ierr = MatGetSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1161e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1171e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
1181e0482f5SStefano Zampini     v    = PetscAbsScalar(vals[0]);
1191e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1201e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1211e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1221e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1231e0482f5SStefano Zampini #if defined(PRINT_GDET)
1241e0482f5SStefano Zampini     {
1251e0482f5SStefano Zampini       PetscViewer viewer;
1261e0482f5SStefano Zampini       char filename[256];
1271e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1281e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1291e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1301e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1311e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1321e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1331e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1341e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1351e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1361e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1371e0482f5SStefano Zampini     }
1381e0482f5SStefano Zampini #endif
1391e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1401e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1411e0482f5SStefano Zampini   }
1421e0482f5SStefano Zampini 
143a13144ffSStefano Zampini   PetscFunctionReturn(0);
144a13144ffSStefano Zampini }
145a13144ffSStefano Zampini 
146a13144ffSStefano Zampini #undef __FUNCT__
147a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCNedelecSupport"
148a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
149a13144ffSStefano Zampini {
150a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
151a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1520569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
153*eee23b56SStefano Zampini   Vec                    tvec;
154a13144ffSStefano Zampini   PetscSF                sfv;
1551e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
156a13144ffSStefano Zampini   MPI_Comm               comm;
157c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
158c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
159b03ebc13SStefano Zampini   PetscBT                btv,bte,btvc,btb,btvcand,btvi,btee,bter;
160a13144ffSStefano Zampini   PetscScalar            *vals,*work;
161a13144ffSStefano Zampini   PetscReal              *rwork;
162a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1631e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
164a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
165*eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
166b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
167a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
168b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
169b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
170b03ebc13SStefano Zampini   PetscInt               *emarks;
171b03ebc13SStefano Zampini #endif
1721e0482f5SStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global;
173a13144ffSStefano Zampini   PetscErrorCode         ierr;
174a13144ffSStefano Zampini 
175a13144ffSStefano Zampini   PetscFunctionBegin;
176a13144ffSStefano Zampini   /* test variable order code and print debug info TODO: to be removed */
177a13144ffSStefano Zampini   print = PETSC_FALSE;
178a13144ffSStefano Zampini   ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_print_nedelec",&print,NULL);CHKERRQ(ierr);
179a13144ffSStefano Zampini   ierr = PetscOptionsGetInt(NULL,NULL,"-pc_bddc_nedelec_order",&pcbddc->nedorder,NULL);CHKERRQ(ierr);
180a13144ffSStefano Zampini 
181a13144ffSStefano Zampini   /* Return to caller if there are no edges in the decomposition */
182a13144ffSStefano Zampini   ierr   = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1831e0482f5SStefano Zampini   ierr   = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
1841e0482f5SStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
185a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
186a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
187c2151214SStefano Zampini   for (i=0;i<n;i++) {
188a13144ffSStefano Zampini     if (PetscRealPart(vals[i]) > 2.) {
189a13144ffSStefano Zampini       lrc[0] = PETSC_TRUE;
190a13144ffSStefano Zampini       break;
191a13144ffSStefano Zampini     }
192a13144ffSStefano Zampini   }
193a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
194a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
195a13144ffSStefano Zampini   if (!lrc[1]) PetscFunctionReturn(0);
196a13144ffSStefano Zampini 
1971e0482f5SStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
1981e0482f5SStefano Zampini      it assumes G is given in global ordering for all the dofs.
1991e0482f5SStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
200a13144ffSStefano Zampini   order      = pcbddc->nedorder;
201a13144ffSStefano Zampini   conforming = pcbddc->conforming;
202c2151214SStefano Zampini   field      = pcbddc->nedfield;
2031e0482f5SStefano Zampini   global     = pcbddc->nedglobal;
204c2151214SStefano 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);
205c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field > -1) {
2061e0482f5SStefano Zampini     PetscBool setprimal = PETSC_FALSE;
2071e0482f5SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field_primal",&setprimal,NULL);CHKERRQ(ierr);
208c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
209c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
210c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
2111e0482f5SStefano Zampini     if (setprimal) {
212*eee23b56SStefano Zampini       IS       enedfieldlocal;
213*eee23b56SStefano Zampini       PetscInt *eidxs;
214*eee23b56SStefano Zampini 
215*eee23b56SStefano Zampini       ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
216*eee23b56SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
217*eee23b56SStefano Zampini       ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
218*eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
219*eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
220*eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
221*eee23b56SStefano Zampini         }
222*eee23b56SStefano Zampini       }
223*eee23b56SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
224*eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
225*eee23b56SStefano Zampini       ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
226*eee23b56SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
227*eee23b56SStefano Zampini       ierr = PetscFree(eidxs);CHKERRQ(ierr);
2281e0482f5SStefano Zampini       ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
229*eee23b56SStefano Zampini       ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2301e0482f5SStefano Zampini       PetscFunctionReturn(0);
2311e0482f5SStefano Zampini     }
2321e0482f5SStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal) {
233c2151214SStefano Zampini     PetscBool testnedfield = PETSC_FALSE;
234c2151214SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field",&testnedfield,NULL);CHKERRQ(ierr);
235c2151214SStefano Zampini     if (!testnedfield) {
236c2151214SStefano Zampini       ne            = n;
237c2151214SStefano Zampini       nedfieldlocal = NULL;
238c2151214SStefano Zampini     } else {
239c2151214SStefano Zampini       /* ierr = ISCreateStride(comm,n,0,1,&nedfieldlocal);CHKERRQ(ierr); */
240c2151214SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
241c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
242c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
243c2151214SStefano Zampini       for (i=0;i<n;i++) matis->sf_leafdata[i] = 1;
244c2151214SStefano Zampini       ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
245c2151214SStefano Zampini       ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
246c2151214SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
247c2151214SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
248c2151214SStefano Zampini       for (i=0,cum=0;i<n;i++) {
249c2151214SStefano Zampini         if (matis->sf_leafdata[i] > 1) {
250c2151214SStefano Zampini           matis->sf_leafdata[cum++] = i;
251c2151214SStefano Zampini         }
252c2151214SStefano Zampini       }
253c2151214SStefano Zampini       ierr = ISCreateGeneral(comm,cum,matis->sf_leafdata,PETSC_COPY_VALUES,&nedfieldlocal);CHKERRQ(ierr);
254c2151214SStefano Zampini       ierr = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
255c2151214SStefano Zampini     }
2561e0482f5SStefano Zampini     global = PETSC_TRUE;
2571e0482f5SStefano Zampini   } else {
2581e0482f5SStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
259c2151214SStefano Zampini   }
260a13144ffSStefano Zampini 
261c2151214SStefano Zampini   if (nedfieldlocal) { /* merge with previous code when testing is done */
262c2151214SStefano Zampini     IS is;
263c2151214SStefano Zampini 
264c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
265c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2661e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2671e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2681e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
2691e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
2701e0482f5SStefano Zampini     if (global) {
2711e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2721e0482f5SStefano Zampini       el2g = al2g;
2731e0482f5SStefano Zampini     } else {
2741e0482f5SStefano Zampini       IS gis;
2751e0482f5SStefano Zampini 
2761e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
2771e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
2781e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
2791e0482f5SStefano Zampini     }
280c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
281c2151214SStefano Zampini   } else {
2821e0482f5SStefano Zampini     /* restore default */
2831e0482f5SStefano Zampini     pcbddc->nedfield = -1;
2841e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
2851e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2861e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2871e0482f5SStefano Zampini     el2g = al2g;
288c2151214SStefano Zampini     fl2g = NULL;
289c2151214SStefano Zampini   }
290a13144ffSStefano Zampini 
291a13144ffSStefano Zampini   /* Sanity checks */
292a13144ffSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
293a13144ffSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
294a13144ffSStefano 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);
295a13144ffSStefano Zampini 
2961e0482f5SStefano Zampini   /* Drop connections for interior edges */
2971e0482f5SStefano Zampini   ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
2981e0482f5SStefano Zampini   ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
299c2151214SStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
300c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
301c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
302c2151214SStefano Zampini   if (nedfieldlocal) {
303c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
304c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
305c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
306c2151214SStefano Zampini   } else {
307c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
308c2151214SStefano Zampini   }
309c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
310c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
3111e0482f5SStefano Zampini   if (global) {
3121e0482f5SStefano Zampini     PetscInt rst;
3131e0482f5SStefano Zampini 
314c2151214SStefano Zampini     ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
315c2151214SStefano Zampini     for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
316c2151214SStefano Zampini       if (matis->sf_rootdata[i] < 2) {
317c2151214SStefano Zampini         matis->sf_rootdata[cum++] = i + rst;
318c2151214SStefano Zampini       }
319c2151214SStefano Zampini     }
320a13144ffSStefano Zampini     ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
321c2151214SStefano Zampini     ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3221e0482f5SStefano Zampini   } else {
3231e0482f5SStefano Zampini     PetscInt *tbz;
3241e0482f5SStefano Zampini 
3251e0482f5SStefano Zampini     ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3261e0482f5SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3271e0482f5SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3281e0482f5SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3291e0482f5SStefano Zampini     for (i=0,cum=0;i<ne;i++)
3301e0482f5SStefano Zampini       if (matis->sf_leafdata[idxs[i]] == 1)
3311e0482f5SStefano Zampini         tbz[cum++] = i;
3321e0482f5SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3331e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3341e0482f5SStefano Zampini     ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3351e0482f5SStefano Zampini     ierr = PetscFree(tbz);CHKERRQ(ierr);
3361e0482f5SStefano Zampini   }
337a13144ffSStefano Zampini 
338a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
339a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
340a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
341a13144ffSStefano Zampini   ierr = MatGetSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
342a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
343a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
344a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
345a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
346a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
347a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
348a13144ffSStefano Zampini   if (print) {
349a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
350a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
351a13144ffSStefano Zampini   }
352a13144ffSStefano Zampini 
353a13144ffSStefano Zampini   /* SF for nodal communications */
354c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
355a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
356a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
357a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
358a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
359a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
360a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
361a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
362a13144ffSStefano Zampini   ierr = PetscMalloc2(nv,&sfvleaves,Lv,&sfvroots);CHKERRQ(ierr);
363a13144ffSStefano Zampini 
3641e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
3651e0482f5SStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
366a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
367a13144ffSStefano Zampini 
3680569b399SStefano Zampini   /* Save lG */
3690569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
3700569b399SStefano Zampini 
371a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
3724e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
3734e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
374a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
377c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
378a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
379a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
380a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
381c2151214SStefano Zampini     IS is;
382c2151214SStefano Zampini 
383c2151214SStefano Zampini     if (fl2g) {
384c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
385c2151214SStefano Zampini     } else {
386c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
387c2151214SStefano Zampini     }
388c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
389c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
390a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
391a13144ffSStefano Zampini       if (idxs[i] >= 0) {
392a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
393a13144ffSStefano Zampini       }
394a13144ffSStefano Zampini     }
395c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
396c2151214SStefano Zampini     if (fl2g) {
397c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
398c2151214SStefano Zampini     }
399a13144ffSStefano Zampini   }
400a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
401c2151214SStefano Zampini     IS is;
402c2151214SStefano Zampini 
403c2151214SStefano Zampini     if (fl2g) {
404c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
405c2151214SStefano Zampini     } else {
406c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
407c2151214SStefano Zampini     }
408c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
409c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
410a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
411a13144ffSStefano Zampini       if (idxs[i] >= 0) {
412a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
413a13144ffSStefano Zampini       }
414a13144ffSStefano Zampini     }
415c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
416c2151214SStefano Zampini     if (fl2g) {
417c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
418a13144ffSStefano Zampini     }
419c2151214SStefano Zampini   }
420c2151214SStefano Zampini 
421a13144ffSStefano Zampini   /* need to remove coarse faces' dofs to ensure the
422a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
423a13144ffSStefano Zampini   ierr = PetscCalloc1(ne,&marks);CHKERRQ(ierr);
42462b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
425a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
42662b0c6f7SStefano Zampini   for (i=1;i<n_neigh;i++)
42762b0c6f7SStefano Zampini     for (j=0;j<n_shared[i];j++)
42862b0c6f7SStefano Zampini       marks[shared[i][j]]++;
429a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
43062b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
43162b0c6f7SStefano Zampini     if (marks[i] > 1 || (marks[i] == 1 && PetscBTLookup(btb,i))) {
43262b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
43362b0c6f7SStefano Zampini     }
43462b0c6f7SStefano Zampini   }
43562b0c6f7SStefano Zampini 
43662b0c6f7SStefano Zampini   if (!conforming) {
43762b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
43862b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
43962b0c6f7SStefano Zampini   }
4404e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
441dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
44262b0c6f7SStefano Zampini   cum  = 0;
443a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
444dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
44562b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
446a13144ffSStefano Zampini       marks[cum++] = i;
447dec27d64SStefano Zampini       continue;
448dec27d64SStefano Zampini     }
449dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
45062b0c6f7SStefano Zampini     if (!conforming) {
45162b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
452a13144ffSStefano Zampini         marks[cum++] = i;
453a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
454a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
455a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
456a13144ffSStefano Zampini         }
45762b0c6f7SStefano Zampini       } else {
45862b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
45962b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
46062b0c6f7SStefano Zampini            - at most 2 endpoints
46162b0c6f7SStefano Zampini            - order-1 interior nodal dofs
46262b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
46362b0c6f7SStefano Zampini         */
46462b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
46562b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
46662b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
46762b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
46862b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
46962b0c6f7SStefano Zampini           if (nconn > order) ends++;
47062b0c6f7SStefano Zampini           else if (nconn == order) ints++;
47162b0c6f7SStefano Zampini           else undef++;
47262b0c6f7SStefano Zampini         }
47362b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
47462b0c6f7SStefano Zampini           marks[cum++] = i;
47562b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
47662b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
47762b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
47862b0c6f7SStefano Zampini           }
47962b0c6f7SStefano Zampini         }
48062b0c6f7SStefano Zampini       }
481a13144ffSStefano Zampini     }
482dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
483dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
484dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
485dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
486a13144ffSStefano Zampini     }
487dec27d64SStefano Zampini   }
48862b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
489dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
4904e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
49162b0c6f7SStefano Zampini   if (!conforming) {
49262b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
49362b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
49462b0c6f7SStefano Zampini   }
4954e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
496b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
4974e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
498a13144ffSStefano Zampini   if (print) {
4994e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5004e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5014e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
502a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
503a13144ffSStefano Zampini   }
504a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
505dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
506a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
507dec27d64SStefano Zampini     PetscInt ord = order, test = ii[i+1]-ii[i];
508b03ebc13SStefano Zampini     if (!order) { /* variable order */
509dec27d64SStefano Zampini       PetscReal vorder = 0.;
510dec27d64SStefano Zampini 
511dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
512dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
513dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
514dec27d64SStefano Zampini       ord  = 1;
515dec27d64SStefano Zampini     }
516a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
517dec27d64SStefano 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);
518a13144ffSStefano Zampini #endif
519dec27d64SStefano Zampini     if (test >= 3*ord) { /* splitpoints */
520a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
521a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
522dec27d64SStefano Zampini     } else if (test == ord) {
523b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
524a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
525a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
526a13144ffSStefano Zampini       } else {
527a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
528a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
529a13144ffSStefano Zampini       }
530a13144ffSStefano Zampini     }
531a13144ffSStefano Zampini   }
532b03ebc13SStefano Zampini 
533b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
534b03ebc13SStefano Zampini   if (order != 1) {
535b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
536b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
537b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
538b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
539b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
540b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
541b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
542b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
543b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
544b03ebc13SStefano Zampini             PetscInt v = jjt[k];
545b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
546b03ebc13SStefano Zampini               found = PETSC_TRUE;
547b03ebc13SStefano Zampini               break;
548b03ebc13SStefano Zampini             }
549b03ebc13SStefano Zampini           }
550b03ebc13SStefano Zampini         }
551b03ebc13SStefano Zampini         if (!found) {
552b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
553b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
554b03ebc13SStefano Zampini         } else {
555b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
556b03ebc13SStefano Zampini         }
557b03ebc13SStefano Zampini       }
558b03ebc13SStefano Zampini     }
559b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
560b03ebc13SStefano Zampini   }
561dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
562a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
563b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
564a13144ffSStefano Zampini 
565a13144ffSStefano Zampini   /* Get the local G^T explicitly */
5660569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
567a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
5684e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
569a13144ffSStefano Zampini 
5704e64d54eSstefano_zampini   /* Mark interior nodal dofs */
571a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
5724e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
573a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
574a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
5754e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
576a13144ffSStefano Zampini     }
577a13144ffSStefano Zampini   }
578a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
579a13144ffSStefano Zampini 
580a13144ffSStefano Zampini   /* communicate corners and splitpoints */
581a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
582a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
583a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
584a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
585a13144ffSStefano Zampini 
586a13144ffSStefano Zampini   if (print) {
587a13144ffSStefano Zampini     IS tbz;
588a13144ffSStefano Zampini 
589a13144ffSStefano Zampini     cum = 0;
590a13144ffSStefano Zampini     for (i=0;i<nv;i++)
591a13144ffSStefano Zampini       if (sfvleaves[i])
592a13144ffSStefano Zampini         vmarks[cum++] = i;
593a13144ffSStefano Zampini 
594a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
595a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
596a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
597a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
598a13144ffSStefano Zampini   }
599a13144ffSStefano Zampini 
600a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
601a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
602a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
603a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
604a13144ffSStefano Zampini 
6054e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6064e64d54eSstefano_zampini      and interior nodal dofs */
607a13144ffSStefano Zampini   cum = 0;
608a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
609a13144ffSStefano Zampini     if (sfvleaves[i]) {
610a13144ffSStefano Zampini       vmarks[cum++] = i;
611a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
612a13144ffSStefano Zampini     }
6134e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
614a13144ffSStefano Zampini   }
6154e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
616a13144ffSStefano Zampini   if (print) {
617a13144ffSStefano Zampini     IS tbz;
618a13144ffSStefano Zampini 
619a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
6204e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
621a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
622a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
623a13144ffSStefano Zampini   }
624a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
625a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
626a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
627a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
628a13144ffSStefano Zampini 
629a13144ffSStefano Zampini   /* Recompute G */
630a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
631a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
632a13144ffSStefano Zampini   if (print) {
633a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
634a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
635a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
636a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
637a13144ffSStefano Zampini   }
638a13144ffSStefano Zampini 
639a13144ffSStefano Zampini   /* Get primal dofs (if any) */
640a13144ffSStefano Zampini   cum = 0;
641a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
642a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
643a13144ffSStefano Zampini   }
644c2151214SStefano Zampini   if (fl2g) {
645c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
646c2151214SStefano Zampini   }
647a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
648a13144ffSStefano Zampini   if (print) {
649a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
650a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
651a13144ffSStefano Zampini   }
652a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
653c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
654a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
655a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
656a13144ffSStefano Zampini 
657a13144ffSStefano Zampini   /* Compute edge connectivity */
658a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
659a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
660a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
661c2151214SStefano Zampini   if (fl2g) {
662c2151214SStefano Zampini     PetscBT   btf;
663c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
664c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
665c2151214SStefano Zampini 
666c2151214SStefano Zampini     /* create CSR for all local dofs */
667c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
668c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
669c2151214SStefano 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);
670c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
671c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
672c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
673c2151214SStefano Zampini       rest = PETSC_TRUE;
674c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
675c2151214SStefano Zampini     } else {
676c2151214SStefano Zampini       free   = PETSC_TRUE;
677c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
678c2151214SStefano Zampini       iiu[0] = 0;
679c2151214SStefano Zampini       for (i=0;i<n;i++) {
680c2151214SStefano Zampini         iiu[i+1] = i+1;
681c2151214SStefano Zampini         jju[i]   = -1;
682d904f53bSStefano Zampini       }
683c2151214SStefano Zampini     }
684c2151214SStefano Zampini 
685c2151214SStefano Zampini     /* import sizes of CSR */
686c2151214SStefano Zampini     iia[0] = 0;
687c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
688c2151214SStefano Zampini 
689c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
690c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
691c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
692c2151214SStefano Zampini     for (i=0;i<ne;i++) {
693c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
694c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
695c2151214SStefano Zampini     }
696c2151214SStefano Zampini 
697c2151214SStefano Zampini     /* iia in CSR */
698c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
699c2151214SStefano Zampini 
700c2151214SStefano Zampini     /* jja in CSR */
701c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
702c2151214SStefano Zampini     for (i=0;i<n;i++)
703c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
704c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
705c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
706c2151214SStefano Zampini 
707c2151214SStefano Zampini     /* map edge dofs connectivity */
7081e0482f5SStefano Zampini     if (jj) {
709c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
710c2151214SStefano Zampini       for (i=0;i<ne;i++) {
711c2151214SStefano Zampini         PetscInt e = idxs[i];
712c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
713c2151214SStefano Zampini       }
7141e0482f5SStefano Zampini     }
715c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
716c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
717c2151214SStefano Zampini     if (rest) {
718c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
719c2151214SStefano Zampini     }
720c2151214SStefano Zampini     if (free) {
721c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
722c2151214SStefano Zampini     }
723c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
724c2151214SStefano Zampini   } else {
7251e0482f5SStefano Zampini     if (jj) {
726c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
727c2151214SStefano Zampini     }
728c2151214SStefano Zampini   }
729c2151214SStefano Zampini 
730a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
731a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
732a13144ffSStefano Zampini 
733a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
734c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
735a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
736a13144ffSStefano Zampini 
737c2151214SStefano Zampini   if (fl2g) {
738c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
739c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
740c2151214SStefano Zampini     for (i=0;i<nee;i++) {
741c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
742c2151214SStefano Zampini     }
743c2151214SStefano Zampini   } else {
744c2151214SStefano Zampini     eedges  = alleedges;
745c2151214SStefano Zampini     primals = allprimals;
746c2151214SStefano Zampini   }
747c2151214SStefano Zampini 
748a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
749a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
750c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
751c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
752c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
753c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
754c2151214SStefano Zampini   if (print) {
755c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
756c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
757c2151214SStefano Zampini   }
758c2151214SStefano Zampini 
759c2151214SStefano Zampini   maxsize = 0;
760a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
761a13144ffSStefano Zampini     PetscInt size,mark = i+1;
762a13144ffSStefano Zampini 
763a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
764a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
765a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
766a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
767a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
768a13144ffSStefano Zampini   }
769a13144ffSStefano Zampini 
770a13144ffSStefano Zampini   /* Find coarse edge endpoints */
771a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
772a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
773a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
774a13144ffSStefano Zampini     PetscInt mark = i+1,size;
775a13144ffSStefano Zampini 
776a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
7771e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
7781e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
779a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
780a13144ffSStefano Zampini     if (print) {
781a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
782a13144ffSStefano Zampini       ISView(eedges[i],NULL);
783a13144ffSStefano Zampini     }
784a13144ffSStefano Zampini     for (j=0;j<size;j++) {
785a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
786a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
787a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
788a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
789a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
790a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
791a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
792a13144ffSStefano Zampini           PetscInt  k2;
793a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
794a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
795c2151214SStefano 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]));
796c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
797c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
798c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
799a13144ffSStefano Zampini               corner = PETSC_TRUE;
800a13144ffSStefano Zampini               break;
801a13144ffSStefano Zampini             }
802a13144ffSStefano Zampini           }
803a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
804a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
805a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
806a13144ffSStefano Zampini           } else {
807a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
808a13144ffSStefano Zampini           }
809a13144ffSStefano Zampini         }
810a13144ffSStefano Zampini       }
811a13144ffSStefano Zampini     }
812a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
813a13144ffSStefano Zampini   }
814a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
815a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
816c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
817a13144ffSStefano Zampini 
818a13144ffSStefano Zampini   /* Reset marked primal dofs */
819a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
820a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
821a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
822a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
823a13144ffSStefano Zampini 
8240569b399SStefano Zampini   /* Now use the initial lG */
8250569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
8260569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
8270569b399SStefano Zampini   lG   = lGinit;
8280569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
8290569b399SStefano Zampini 
830a13144ffSStefano Zampini   /* Compute extended cols indices */
831b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
832b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
833a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
834a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
835a13144ffSStefano Zampini   i   *= maxsize;
836b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
837a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
838a13144ffSStefano Zampini   eerr = PETSC_FALSE;
839a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
840b03ebc13SStefano Zampini     PetscInt size,found = 0;
841a13144ffSStefano Zampini 
842a13144ffSStefano Zampini     cum  = 0;
843a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8441e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8451e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
846a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
847b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
848a13144ffSStefano Zampini     for (j=0;j<size;j++) {
849a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
850b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
851b03ebc13SStefano Zampini         PetscInt vv = jj[k];
852b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
853b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
854b03ebc13SStefano Zampini       }
855a13144ffSStefano Zampini     }
856a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
857a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
858a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
859a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
860a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
861a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
862a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
863b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
864b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
865a13144ffSStefano Zampini       if (print) {
866a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
867a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
868a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
869a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
870a13144ffSStefano Zampini       }
871a13144ffSStefano Zampini       eerr = PETSC_TRUE;
872a13144ffSStefano Zampini     }
873a13144ffSStefano Zampini   }
8744e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
875a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
876a13144ffSStefano Zampini   if (done) {
877a13144ffSStefano Zampini     PetscInt *newprimals;
878a13144ffSStefano Zampini 
879a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
880a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
881a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
882a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
883a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
8840569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
885b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
886a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
887b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
888b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
889a13144ffSStefano Zampini         PetscInt size,mark = i+1;
890a13144ffSStefano Zampini 
891a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
892a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
893c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
894a13144ffSStefano Zampini         for (j=0;j<size;j++) {
895a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
896b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
897a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
898a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
899a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
900a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
901b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
902b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
903a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
904a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
905a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
906a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
907a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
908b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
909a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
910a13144ffSStefano Zampini                   /* finally set the new corners */
911a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
912b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
913a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
914a13144ffSStefano Zampini                   }
915a13144ffSStefano Zampini                 }
916a13144ffSStefano Zampini               }
917b03ebc13SStefano Zampini             } else {
918b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
919a13144ffSStefano Zampini             }
920a13144ffSStefano Zampini           }
921a13144ffSStefano Zampini         }
922b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
923b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
924b03ebc13SStefano Zampini 
925b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
926b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
927b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
928b03ebc13SStefano Zampini             PetscInt k2;
929b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
930b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
931b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
932b03ebc13SStefano Zampini           }
933b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
934b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
935b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
936b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
937b03ebc13SStefano Zampini             }
938b03ebc13SStefano Zampini           }
939b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
940b03ebc13SStefano Zampini         }
941a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
942a13144ffSStefano Zampini       }
943a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
944a13144ffSStefano Zampini     }
945b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
9460569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
947a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
948c2151214SStefano Zampini     if (fl2g) {
949c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
950c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
951c2151214SStefano Zampini       for (i=0;i<nee;i++) {
952c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
953c2151214SStefano Zampini       }
954c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
955c2151214SStefano Zampini     }
956c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
957a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
958a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
959a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
960a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
961a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
962c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
963c2151214SStefano Zampini     if (fl2g) {
964c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
965c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
966c2151214SStefano Zampini       for (i=0;i<nee;i++) {
967c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
968c2151214SStefano Zampini       }
969c2151214SStefano Zampini     } else {
970c2151214SStefano Zampini       eedges  = alleedges;
971c2151214SStefano Zampini       primals = allprimals;
972c2151214SStefano Zampini     }
973b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
974a13144ffSStefano Zampini 
975a13144ffSStefano Zampini     /* Mark again */
976a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
977a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
978a13144ffSStefano Zampini       PetscInt size,mark = i+1;
979a13144ffSStefano Zampini 
980a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
981a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
982a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
983a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
984a13144ffSStefano Zampini     }
985a13144ffSStefano Zampini     if (print) {
986a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
987a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
988a13144ffSStefano Zampini     }
989a13144ffSStefano Zampini 
990a13144ffSStefano Zampini     /* Recompute extended cols */
991a13144ffSStefano Zampini     eerr = PETSC_FALSE;
992a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
993a13144ffSStefano Zampini       PetscInt size;
994a13144ffSStefano Zampini 
995a13144ffSStefano Zampini       cum  = 0;
996a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9971e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
9981e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
999a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1000a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1001a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10021e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1003a13144ffSStefano Zampini       }
1004a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1005a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1006a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1007a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1008a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1009a13144ffSStefano Zampini       if (cum != size -1) {
1010a13144ffSStefano Zampini         if (print) {
1011a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1012a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1013a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1014a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1015a13144ffSStefano Zampini         }
1016a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1017a13144ffSStefano Zampini       }
1018a13144ffSStefano Zampini     }
1019a13144ffSStefano Zampini   }
1020a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1021a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1022b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
1023a13144ffSStefano Zampini   /* an error should not occur at this point */
1024a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1025b03ebc13SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1026a13144ffSStefano Zampini 
10274e64d54eSstefano_zampini   /* Check the number of endpoints */
10280569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1029b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1030b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
10314e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1032b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
10334e64d54eSstefano_zampini 
1034b03ebc13SStefano Zampini     /* init with defaults */
1035b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
10364e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10371e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
10381e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
10394e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1040b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
10414e64d54eSstefano_zampini     for (j=0;j<size;j++) {
10424e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
10434e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
10444e64d54eSstefano_zampini         PetscInt vv = jj[k];
10454e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1046b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1047b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
10484e64d54eSstefano_zampini         }
10494e64d54eSstefano_zampini       }
10504e64d54eSstefano_zampini     }
1051b03ebc13SStefano Zampini     if (found != 2) {
1052b03ebc13SStefano Zampini       PetscInt e;
1053b03ebc13SStefano Zampini       if (fl2g) {
1054b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1055b03ebc13SStefano Zampini       } else {
1056b03ebc13SStefano Zampini         e = idxs[0];
1057b03ebc13SStefano Zampini       }
1058b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1059b03ebc13SStefano Zampini     }
1060*eee23b56SStefano Zampini 
1061*eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1062b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1063b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1064b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1065b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1066b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1067b03ebc13SStefano Zampini     }
1068*eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
10694e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1070b03ebc13SStefano 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]);
10714e64d54eSstefano_zampini   }
10720569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
10734e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
10744e64d54eSstefano_zampini 
1075a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1076a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1077a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1078a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1079a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1080a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1081a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1082a13144ffSStefano Zampini 
1083a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1084a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1085a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1086a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1087a13144ffSStefano Zampini       if (emax < emarks[j]) {
1088a13144ffSStefano Zampini         emax = emarks[j];
1089a13144ffSStefano Zampini         eemax = j;
1090a13144ffSStefano Zampini       }
1091a13144ffSStefano Zampini     }
1092a13144ffSStefano Zampini     /* not relevant for edges */
1093a13144ffSStefano Zampini     if (!eemax) continue;
1094a13144ffSStefano Zampini 
1095a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1096a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1097c2151214SStefano 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]);
1098a13144ffSStefano Zampini       }
1099a13144ffSStefano Zampini     }
1100a13144ffSStefano Zampini   }
1101a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1102a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1103a13144ffSStefano Zampini #endif
1104a13144ffSStefano Zampini 
1105a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1106a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1107a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1108a13144ffSStefano Zampini   extmem *= maxsize;
1109a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1110a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1111a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1112a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1113a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1114a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1115a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1116a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1117a13144ffSStefano Zampini         mark = marks[jj[j]];
1118a13144ffSStefano Zampini 
1119a13144ffSStefano Zampini     /* not relevant */
1120a13144ffSStefano Zampini     if (!mark) continue;
1121a13144ffSStefano Zampini 
1122a13144ffSStefano Zampini     /* import extended row */
1123a13144ffSStefano Zampini     mark--;
1124a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1125a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1126a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1127a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1128a13144ffSStefano Zampini     extrowcum[mark] += size;
1129a13144ffSStefano Zampini   }
1130a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1131a13144ffSStefano Zampini   cum  = 0;
1132a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1133a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1134a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1135a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1136a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1137a13144ffSStefano Zampini   }
1138a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1139a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1140a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1141a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1142a13144ffSStefano Zampini 
1143a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1144a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1145a13144ffSStefano Zampini 
1146a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1147a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1148c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1149c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1150a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1151a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1152a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
11531e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1154a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1155a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1156a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
1157a13144ffSStefano Zampini 
1158a13144ffSStefano Zampini   /* Defaults to identity */
1159c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1160a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1161a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1162a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1163a13144ffSStefano Zampini 
11641e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
11651e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
11661e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
11671e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
11681e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
11691e0482f5SStefano Zampini     IS                     wis,gwis;
11701e0482f5SStefano Zampini     PetscInt               cnv,cne;
11711e0482f5SStefano Zampini 
11721e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
11731e0482f5SStefano Zampini     if (fl2g) {
11741e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
11751e0482f5SStefano Zampini     } else {
11761e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
11771e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
11781e0482f5SStefano Zampini     }
11791e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
11801e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
11811e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
11821e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
11831e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
11841e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
11851e0482f5SStefano Zampini 
11861e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
11871e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
11881e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
11891e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
11901e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
11911e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
11921e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
11931e0482f5SStefano Zampini 
11941e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
11951e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
11961e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
11971e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
11981e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
11991e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12001e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12011e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12021e0482f5SStefano Zampini   }
12031e0482f5SStefano Zampini 
12041e0482f5SStefano Zampini #if defined(PRINT_GDET)
12051e0482f5SStefano Zampini   inc = 0;
12061e0482f5SStefano Zampini   lev = pcbddc->current_level;
12071e0482f5SStefano Zampini #endif
1208a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1209a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12101e0482f5SStefano Zampini     IS          cornersis = NULL;
12111e0482f5SStefano Zampini     PetscScalar cvals[2];
1212a13144ffSStefano Zampini 
12131e0482f5SStefano Zampini     if (pcbddc->nedcG) {
12141e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
12151e0482f5SStefano Zampini     }
12161e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1217a13144ffSStefano Zampini     if (Gins && GKins) {
1218a13144ffSStefano Zampini       PetscScalar    *data;
1219a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1220a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1221a13144ffSStefano Zampini 
1222a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1223a13144ffSStefano Zampini       /* H1 */
1224a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1225a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1226a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1227a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1228a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1229a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1230a13144ffSStefano Zampini       /* complement */
1231a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
12321e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1233a13144ffSStefano Zampini       if (ncc + nch != nrc) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %d and Gins %d does not match %d",ncc,nch,nrc);
12341e0482f5SStefano Zampini       if (ncc != 1 && pcbddc->nedcG) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the dicrete gradient for the next level with ncc %d",ncc);
1235a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1236a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1237a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
12381e0482f5SStefano Zampini 
12391e0482f5SStefano Zampini       /* coarse discrete gradient */
12401e0482f5SStefano Zampini       if (pcbddc->nedcG) {
12411e0482f5SStefano Zampini         PetscInt cols[2];
12421e0482f5SStefano Zampini 
12431e0482f5SStefano Zampini         cols[0] = 2*i;
12441e0482f5SStefano Zampini         cols[1] = 2*i+1;
12451e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
12461e0482f5SStefano Zampini       }
1247a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1248a13144ffSStefano Zampini     }
1249a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1250a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
12511e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1252a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1253a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1254a13144ffSStefano Zampini   }
1255a13144ffSStefano Zampini 
1256a13144ffSStefano Zampini   /* Start assembling */
1257a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12581e0482f5SStefano Zampini   if (pcbddc->nedcG) {
12591e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12601e0482f5SStefano Zampini   }
1261a13144ffSStefano Zampini 
1262a13144ffSStefano Zampini   /* Free */
1263c2151214SStefano Zampini   if (fl2g) {
1264c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1265c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1266c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1267c2151214SStefano Zampini     }
1268c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1269c2151214SStefano Zampini   }
1270*eee23b56SStefano Zampini 
1271*eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1272*eee23b56SStefano Zampini   {
1273*eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1274*eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1275*eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1276*eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1277*eee23b56SStefano Zampini 
1278*eee23b56SStefano Zampini     /* find first primal edge */
1279*eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1280*eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1281*eee23b56SStefano Zampini     } else {
1282*eee23b56SStefano Zampini       if (fl2g) {
1283*eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1284*eee23b56SStefano Zampini       }
1285*eee23b56SStefano Zampini       idxs = cedges;
1286*eee23b56SStefano Zampini     }
1287*eee23b56SStefano Zampini     cum = 0;
1288*eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1289*eee23b56SStefano Zampini 
1290*eee23b56SStefano Zampini     /* adapt connected components */
1291*eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1292*eee23b56SStefano Zampini     graph->cptr[0] = 0;
1293*eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1294*eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1295*eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1296*eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1297*eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1298*eee23b56SStefano Zampini         ncc++;
1299*eee23b56SStefano Zampini         lc--;
1300*eee23b56SStefano Zampini         cum++;
1301*eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1302*eee23b56SStefano Zampini       }
1303*eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1304*eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1305*eee23b56SStefano Zampini       ncc++;
1306*eee23b56SStefano Zampini     }
1307*eee23b56SStefano Zampini     graph->ncc = ncc;
1308*eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1309*eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1310*eee23b56SStefano Zampini     }
1311*eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1312*eee23b56SStefano Zampini   }
1313c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1314c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1315*eee23b56SStefano Zampini 
1316*eee23b56SStefano Zampini 
1317c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1318a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1319a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
1320c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
13211e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1322c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1323a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1324b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1325b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1326a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1327a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1328a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1329a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1330a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1331a13144ffSStefano Zampini 
1332a13144ffSStefano Zampini   /* Complete assembling */
1333a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13341e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13351e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13361e0482f5SStefano Zampini #if 0
13371e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
13381e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
13391e0482f5SStefano Zampini #endif
13401e0482f5SStefano Zampini   }
1341a13144ffSStefano Zampini 
1342a13144ffSStefano Zampini   /* set change of basis */
1343a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
13441e0482f5SStefano Zampini #if 0
13451e0482f5SStefano Zampini   if (pcbddc->current_level) {
13461e0482f5SStefano Zampini     PetscViewer viewer;
13471e0482f5SStefano Zampini     char filename[256];
13481e0482f5SStefano Zampini     Mat  Tned;
13491e0482f5SStefano Zampini     IS   sub;
13501e0482f5SStefano Zampini     PetscInt rst;
13511e0482f5SStefano Zampini 
13521e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
13531e0482f5SStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
13541e0482f5SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
13551e0482f5SStefano Zampini     if (nedfieldlocal) {
13561e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
13571e0482f5SStefano Zampini       for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
13581e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
13591e0482f5SStefano Zampini     } else {
13601e0482f5SStefano Zampini       for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
13611e0482f5SStefano Zampini     }
13621e0482f5SStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
13631e0482f5SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
13641e0482f5SStefano Zampini     ierr = MatGetOwnershipRange(pc->pmat,&rst,NULL);CHKERRQ(ierr);
13651e0482f5SStefano Zampini     for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
13661e0482f5SStefano Zampini       if (matis->sf_rootdata[i]) {
13671e0482f5SStefano Zampini         matis->sf_rootdata[cum++] = i + rst;
13681e0482f5SStefano Zampini       }
13691e0482f5SStefano Zampini     }
13701e0482f5SStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%D] LEVEL %d MY ne %d cum %d\n",PetscGlobalRank,pcbddc->current_level,ne,cum);
13711e0482f5SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cum,matis->sf_rootdata,PETSC_USE_POINTER,&sub);CHKERRQ(ierr);
13721e0482f5SStefano Zampini     ierr = MatGetSubMatrix(T,sub,sub,MAT_INITIAL_MATRIX,&Tned);CHKERRQ(ierr);
13731e0482f5SStefano Zampini     ierr = ISDestroy(&sub);CHKERRQ(ierr);
13741e0482f5SStefano Zampini 
13751e0482f5SStefano Zampini     sprintf(filename,"Change_l%d.m",pcbddc->current_level);
13761e0482f5SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)Tned),filename,&viewer);CHKERRQ(ierr);
13771e0482f5SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
13781e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)Tned,"T");CHKERRQ(ierr);
13791e0482f5SStefano Zampini     ierr = MatView(Tned,viewer);CHKERRQ(ierr);
13801e0482f5SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
13811e0482f5SStefano Zampini     ierr = MatDestroy(&Tned);CHKERRQ(ierr);
13821e0482f5SStefano Zampini   }
13831e0482f5SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
13841e0482f5SStefano Zampini #endif
1385a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1386a13144ffSStefano Zampini 
1387a13144ffSStefano Zampini   PetscFunctionReturn(0);
1388a13144ffSStefano Zampini }
1389a13144ffSStefano Zampini 
1390d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1391d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1392d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1393d8203eabSStefano Zampini #undef __FUNCT__
1394d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1395d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1396d8203eabSStefano Zampini {
1397d8203eabSStefano Zampini   PetscErrorCode ierr;
1398d8203eabSStefano Zampini   PetscInt       i;
1399d8203eabSStefano Zampini 
1400d8203eabSStefano Zampini   PetscFunctionBegin;
1401d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1402d8203eabSStefano Zampini     PetscInt first,last;
1403d8203eabSStefano Zampini 
1404d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
140586fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1406d8203eabSStefano Zampini     if (i>=first && i < last) {
1407d8203eabSStefano Zampini       PetscScalar *data;
1408d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1409d8203eabSStefano Zampini       if (!has_const) {
1410d8203eabSStefano Zampini         data[i-first] = 1.;
1411d8203eabSStefano Zampini       } else {
141286fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
141386fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1414d8203eabSStefano Zampini       }
1415d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1416d8203eabSStefano Zampini     }
1417d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1418d8203eabSStefano Zampini   }
1419d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1420d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1421d8203eabSStefano Zampini     PetscInt first,last;
1422d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1423d8203eabSStefano Zampini     if (i>=first && i < last) {
1424d8203eabSStefano Zampini       PetscScalar *data;
1425d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1426d8203eabSStefano Zampini       if (!has_const) {
1427d8203eabSStefano Zampini         data[i-first] = 0.;
1428d8203eabSStefano Zampini       } else {
142986fa73c5SStefano Zampini         data[2*i-first] = 0.;
143086fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1431d8203eabSStefano Zampini       }
1432d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1433d8203eabSStefano Zampini     }
1434d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1435d8203eabSStefano Zampini   }
1436d8203eabSStefano Zampini   PetscFunctionReturn(0);
1437d8203eabSStefano Zampini }
1438d8203eabSStefano Zampini 
1439669cc0f4SStefano Zampini #undef __FUNCT__
1440669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
14418ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1442669cc0f4SStefano Zampini {
1443a198735bSStefano Zampini   Mat                    loc_divudotp;
1444fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14458ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1446669cc0f4SStefano Zampini   IS                     *faces,*edges;
1447669cc0f4SStefano Zampini   PetscScalar            *vals;
1448669cc0f4SStefano Zampini   const PetscScalar      *array;
1449669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
14501ae86dd6SStefano Zampini   PetscMPIInt            rank;
1451a198735bSStefano Zampini   PetscErrorCode         ierr;
1452669cc0f4SStefano Zampini 
1453669cc0f4SStefano Zampini   PetscFunctionBegin;
1454669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1455669cc0f4SStefano Zampini   if (graph->twodim) {
1456669cc0f4SStefano Zampini     lmaxneighs = 2;
1457669cc0f4SStefano Zampini   } else {
1458669cc0f4SStefano Zampini     lmaxneighs = 1;
1459669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1460669cc0f4SStefano Zampini       const PetscInt *idxs;
1461669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1462669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1463669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1464669cc0f4SStefano Zampini     }
1465669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1466669cc0f4SStefano Zampini   }
1467669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1468669cc0f4SStefano Zampini   maxsize = 0;
1469669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1470669cc0f4SStefano Zampini     PetscInt nn;
1471669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1472669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1473669cc0f4SStefano Zampini   }
1474669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1475669cc0f4SStefano Zampini     PetscInt nn;
1476669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1477669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1478669cc0f4SStefano Zampini   }
1479669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1480669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1481669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
14828ae0ca82SStefano Zampini   if (!transpose) {
14838ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
14848ae0ca82SStefano Zampini   } else {
14858ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
14868ae0ca82SStefano Zampini   }
1487669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
14881ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1489d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1490669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
14918ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1492669cc0f4SStefano Zampini   }
1493d8203eabSStefano Zampini 
1494669cc0f4SStefano Zampini   /* compute local quad vec */
1495a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
14968ae0ca82SStefano Zampini   if (!transpose) {
1497a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
14988ae0ca82SStefano Zampini   } else {
14998ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15008ae0ca82SStefano Zampini   }
1501669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15028ae0ca82SStefano Zampini   if (!transpose) {
1503a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15048ae0ca82SStefano Zampini   } else {
15058ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15068ae0ca82SStefano Zampini   }
1507fa23a32eSStefano Zampini   if (vl2l) {
1508fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1509fa23a32eSStefano Zampini   } else {
1510fa23a32eSStefano Zampini     vins = v;
1511fa23a32eSStefano Zampini   }
1512fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1513669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
15149a962809SStefano Zampini 
15151ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
15161ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1517669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1518669cc0f4SStefano Zampini     const PetscInt    *idxs;
1519669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1520669cc0f4SStefano Zampini 
1521669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1522669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1523669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15241ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1525669cc0f4SStefano Zampini     idx = -(idx+1);
1526669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1527669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1528669cc0f4SStefano Zampini   }
1529669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1530669cc0f4SStefano Zampini     const PetscInt    *idxs;
1531669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1532669cc0f4SStefano Zampini 
1533669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1534669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1535669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
15361ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1537669cc0f4SStefano Zampini     idx = -(idx+1);
1538669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1539669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1540669cc0f4SStefano Zampini   }
1541c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1542fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1543fa23a32eSStefano Zampini   if (vl2l) {
1544fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1545fa23a32eSStefano Zampini   }
1546669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1547669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1548669cc0f4SStefano Zampini 
1549669cc0f4SStefano Zampini   /* assemble near null space */
1550669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1551669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1552669cc0f4SStefano Zampini   }
1553669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1554669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1555669cc0f4SStefano Zampini   }
1556669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1557669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1558669cc0f4SStefano Zampini }
1559669cc0f4SStefano Zampini 
1560669cc0f4SStefano Zampini 
1561a3df083aSStefano Zampini #undef __FUNCT__
15621f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
15631f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
15641f4df5f7SStefano Zampini {
15651f4df5f7SStefano Zampini   PetscErrorCode ierr;
15661f4df5f7SStefano Zampini   Vec            local,global;
15671f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
15681f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
15691f4df5f7SStefano Zampini 
15701f4df5f7SStefano Zampini   PetscFunctionBegin;
15711f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
15721f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
15731f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
15741f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
15751f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
15761f4df5f7SStefano Zampini       PetscInt i;
15771f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
15781f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
15791f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
15801f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
15811f4df5f7SStefano Zampini       }
15821f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
15831f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
15841f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
15851f4df5f7SStefano Zampini     }
15861f4df5f7SStefano Zampini   } else {
1587986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
15881f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1589986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1590986cdee1SStefano Zampini       if (i > 1) {
1591986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
15921f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
15931f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
15941f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
15951f4df5f7SStefano Zampini         }
15961f4df5f7SStefano Zampini       }
15971f4df5f7SStefano Zampini     }
1598986cdee1SStefano Zampini   }
15991f4df5f7SStefano Zampini 
16001f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16011f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16021f4df5f7SStefano Zampini   }
16031f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16041f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16051f4df5f7SStefano Zampini   }
16061f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16071f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16081f4df5f7SStefano Zampini   }
16091f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16101f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16111f4df5f7SStefano Zampini   PetscFunctionReturn(0);
16121f4df5f7SStefano Zampini }
16131f4df5f7SStefano Zampini 
16141f4df5f7SStefano Zampini #undef __FUNCT__
16153e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
16163e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
16173e589ea0SStefano Zampini {
16183e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
16193e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
16203e589ea0SStefano Zampini   PetscErrorCode    ierr;
16213e589ea0SStefano Zampini 
16223e589ea0SStefano Zampini   PetscFunctionBegin;
16233e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
16243e589ea0SStefano Zampini     PetscFunctionReturn(0);
16253e589ea0SStefano Zampini   }
16263e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
16273e589ea0SStefano Zampini     Vec swap;
16283e589ea0SStefano Zampini 
16293e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
16303e589ea0SStefano Zampini     swap = pcbddc->work_change;
16313e589ea0SStefano Zampini     pcbddc->work_change = r;
16323e589ea0SStefano Zampini     r = swap;
16333e589ea0SStefano Zampini   }
16343e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16353e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16363e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
16373e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
16383e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16393e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16403e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1641f913dca9SStefano Zampini     pcbddc->work_change = r;
16423e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
16433e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
16443e589ea0SStefano Zampini   }
16453e589ea0SStefano Zampini   PetscFunctionReturn(0);
16463e589ea0SStefano Zampini }
16473e589ea0SStefano Zampini 
16483e589ea0SStefano Zampini #undef __FUNCT__
1649a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1650a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1651a3df083aSStefano Zampini {
1652a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1653a3df083aSStefano Zampini   PetscErrorCode          ierr;
1654a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1655a3df083aSStefano Zampini 
1656a3df083aSStefano Zampini   PetscFunctionBegin;
1657a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1658a3df083aSStefano Zampini   if (transpose) {
1659a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1660a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1661a3df083aSStefano Zampini   } else {
1662a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1663a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1664a3df083aSStefano Zampini   }
1665a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1666a3df083aSStefano Zampini   if (apply_right) {
1667a3df083aSStefano Zampini     const PetscScalar *ax;
1668a3df083aSStefano Zampini     PetscInt          nl,i;
1669a3df083aSStefano Zampini 
1670a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1671a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1672a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1673a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1674a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1675a3df083aSStefano Zampini       PetscScalar    sum,val;
1676a3df083aSStefano Zampini       const PetscInt *idxs;
1677a3df083aSStefano Zampini       PetscInt       nz,j;
1678a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1679a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1680a3df083aSStefano Zampini       sum = 0.;
1681a3df083aSStefano Zampini       if (ctx->apply_p0) {
1682a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1683a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1684a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1685a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1686a3df083aSStefano Zampini         }
1687a3df083aSStefano Zampini       } else {
1688a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1689a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1690a3df083aSStefano Zampini         }
1691a3df083aSStefano Zampini       }
1692a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1693a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1694a3df083aSStefano Zampini     }
1695a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1696a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1697a3df083aSStefano Zampini   }
1698a3df083aSStefano Zampini   if (transpose) {
1699a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1700a3df083aSStefano Zampini   } else {
1701a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1702a3df083aSStefano Zampini   }
1703a3df083aSStefano Zampini   if (reset_x) {
1704a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1705a3df083aSStefano Zampini   }
1706a3df083aSStefano Zampini   if (apply_left) {
1707a3df083aSStefano Zampini     PetscScalar *ay;
1708a3df083aSStefano Zampini     PetscInt    i;
1709a3df083aSStefano Zampini 
1710a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1711a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1712a3df083aSStefano Zampini       PetscScalar    sum,val;
1713a3df083aSStefano Zampini       const PetscInt *idxs;
1714a3df083aSStefano Zampini       PetscInt       nz,j;
1715a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1716a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1717a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1718a3df083aSStefano Zampini       if (ctx->apply_p0) {
1719a3df083aSStefano Zampini         sum = 0.;
1720a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1721a3df083aSStefano Zampini           sum += ay[idxs[j]];
1722a3df083aSStefano Zampini           ay[idxs[j]] += val;
1723a3df083aSStefano Zampini         }
1724a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1725a3df083aSStefano Zampini       } else {
1726a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1727a3df083aSStefano Zampini           ay[idxs[j]] += val;
1728a3df083aSStefano Zampini         }
1729a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1730a3df083aSStefano Zampini       }
1731a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1732a3df083aSStefano Zampini     }
1733a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1734a3df083aSStefano Zampini   }
1735a3df083aSStefano Zampini   PetscFunctionReturn(0);
1736a3df083aSStefano Zampini }
1737a3df083aSStefano Zampini 
1738a3df083aSStefano Zampini #undef __FUNCT__
1739a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1740a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1741a3df083aSStefano Zampini {
1742a3df083aSStefano Zampini   PetscErrorCode ierr;
1743a3df083aSStefano Zampini 
1744a3df083aSStefano Zampini   PetscFunctionBegin;
1745a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1746a3df083aSStefano Zampini   PetscFunctionReturn(0);
1747a3df083aSStefano Zampini }
1748a3df083aSStefano Zampini 
1749a3df083aSStefano Zampini #undef __FUNCT__
1750a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1751a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1752a3df083aSStefano Zampini {
1753a3df083aSStefano Zampini   PetscErrorCode ierr;
1754a3df083aSStefano Zampini 
1755a3df083aSStefano Zampini   PetscFunctionBegin;
1756a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1757a3df083aSStefano Zampini   PetscFunctionReturn(0);
1758a3df083aSStefano Zampini }
1759a3df083aSStefano Zampini 
1760a3df083aSStefano Zampini #undef __FUNCT__
1761a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1762a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1763a3df083aSStefano Zampini {
1764a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1765a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1766a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1767a3df083aSStefano Zampini   PetscErrorCode          ierr;
1768a3df083aSStefano Zampini 
1769a3df083aSStefano Zampini   PetscFunctionBegin;
1770a3df083aSStefano Zampini   if (!restore) {
17711dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1772a3df083aSStefano Zampini     PetscScalar        *work;
1773b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1774a3df083aSStefano Zampini 
17759a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
17769a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1777a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1778a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1779a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1780a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1781a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1782a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1783a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1784a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1785a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1786a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1787a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1788a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1789059032f7SStefano Zampini     if (reuse) {
1790a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
17911dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1792059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1793059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1794059032f7SStefano Zampini       PetscInt               i;
1795059032f7SStefano Zampini 
1796059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1797059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1798059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1799059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1800059032f7SStefano Zampini       }
1801059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
18021dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1803059032f7SStefano Zampini     }
1804a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1805a3df083aSStefano Zampini     ctx->work = work;
1806a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1807a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1808a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1809a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1810a3df083aSStefano Zampini 
1811a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1812a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1813a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1814a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1815a3df083aSStefano Zampini   } else {
18161dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
18171dd7afcfSStefano Zampini       PetscFunctionReturn(0);
18181dd7afcfSStefano Zampini     }
1819a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1820a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1821a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
18221dd7afcfSStefano Zampini     ctx->A = NULL;
18231dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18241dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
18251dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
18261dd7afcfSStefano Zampini     if (ctx->free) {
1827059032f7SStefano Zampini       PetscInt i;
18281dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1829059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1830059032f7SStefano Zampini       }
1831059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1832059032f7SStefano Zampini     }
1833a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1834a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1835a3df083aSStefano Zampini   }
1836a3df083aSStefano Zampini   PetscFunctionReturn(0);
1837a3df083aSStefano Zampini }
1838a3df083aSStefano Zampini 
1839a3df083aSStefano Zampini /* used just in bddc debug mode */
1840a3df083aSStefano Zampini #undef __FUNCT__
1841a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1842a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1843a3df083aSStefano Zampini {
1844a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1845a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1846a3df083aSStefano Zampini   Mat            An;
1847a3df083aSStefano Zampini   PetscErrorCode ierr;
1848a3df083aSStefano Zampini 
1849a3df083aSStefano Zampini   PetscFunctionBegin;
1850a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1851a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1852a3df083aSStefano Zampini   if (is1) {
1853a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1854a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1855a3df083aSStefano Zampini   } else {
1856a3df083aSStefano Zampini     *B = An;
1857a3df083aSStefano Zampini   }
1858a3df083aSStefano Zampini   PetscFunctionReturn(0);
1859a3df083aSStefano Zampini }
1860a3df083aSStefano Zampini 
18611cf9b237SStefano Zampini /* TODO: add reuse flag */
18621cf9b237SStefano Zampini #undef __FUNCT__
18631cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
18641cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
18651cf9b237SStefano Zampini {
18661cf9b237SStefano Zampini   Mat            Bt;
18671cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
18681cf9b237SStefano Zampini   const PetscInt *ii,*ij;
18691cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
18701cf9b237SStefano Zampini   PetscBool      flg_row;
18711cf9b237SStefano Zampini   PetscErrorCode ierr;
18721cf9b237SStefano Zampini 
18731cf9b237SStefano Zampini   PetscFunctionBegin;
18741cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
18751cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
18761cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
18771cf9b237SStefano Zampini   nnz = n;
18781cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
18791cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
18801cf9b237SStefano Zampini   }
18811cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
18821cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
18831cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
18841cf9b237SStefano Zampini   nnz = 0;
18851cf9b237SStefano Zampini   bii[0] = 0;
18861cf9b237SStefano Zampini   for (i=0;i<n;i++) {
18871cf9b237SStefano Zampini     PetscInt j;
18881cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
18891cf9b237SStefano Zampini       PetscScalar entry = a[j];
18901cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
18911cf9b237SStefano Zampini         bij[nnz] = ij[j];
18921cf9b237SStefano Zampini         bdata[nnz] = entry;
18931cf9b237SStefano Zampini         nnz++;
18941cf9b237SStefano Zampini       }
18951cf9b237SStefano Zampini     }
18961cf9b237SStefano Zampini     bii[i+1] = nnz;
18971cf9b237SStefano Zampini   }
18981cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
18991cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
19001cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
19011cf9b237SStefano Zampini   {
19021cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
19031cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
19041cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
19051cf9b237SStefano Zampini   }
19061cf9b237SStefano Zampini   *B = Bt;
19071cf9b237SStefano Zampini   PetscFunctionReturn(0);
19081cf9b237SStefano Zampini }
19091cf9b237SStefano Zampini 
1910674ae819SStefano Zampini #undef __FUNCT__
19114f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
19124f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
19134f1b2e48SStefano Zampini {
19144f1b2e48SStefano Zampini   Mat                    B;
19154f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
19164f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
19174f1b2e48SStefano Zampini   PCBDDCGraph            graph;
19184f1b2e48SStefano Zampini   PetscInt               i,n;
19194f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
19204f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
19214f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
19224f1b2e48SStefano Zampini   PetscErrorCode         ierr;
19234f1b2e48SStefano Zampini 
19244f1b2e48SStefano Zampini   PetscFunctionBegin;
192563c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
192663c961adSStefano Zampini     *ncc = 0;
192763c961adSStefano Zampini     *cc = NULL;
192863c961adSStefano Zampini     PetscFunctionReturn(0);
192963c961adSStefano Zampini   }
19304f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
19314f1b2e48SStefano Zampini   if (!isseqaij && filter) {
19321cf9b237SStefano Zampini     PetscBool isseqdense;
19331cf9b237SStefano Zampini 
19341cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
19351cf9b237SStefano Zampini     if (!isseqdense) {
19364f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
19371cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
19381cf9b237SStefano Zampini       PetscScalar *array;
19391cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
19401cf9b237SStefano Zampini 
19411cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
19421cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
19431cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
19441cf9b237SStefano Zampini       for (i=0;i<n;i++) {
19451cf9b237SStefano Zampini         PetscInt j;
19461cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
19471cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
19481cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
19491cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
19501cf9b237SStefano Zampini         }
19511cf9b237SStefano Zampini       }
19521cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
19539d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
19541cf9b237SStefano Zampini     }
19554f1b2e48SStefano Zampini   } else {
19564f1b2e48SStefano Zampini     B = A;
19574f1b2e48SStefano Zampini   }
19584f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
19594f1b2e48SStefano Zampini 
19604f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
19614f1b2e48SStefano Zampini   if (filter) {
19624f1b2e48SStefano Zampini     PetscScalar *data;
19634f1b2e48SStefano Zampini     PetscInt    j,cum;
19644f1b2e48SStefano Zampini 
19654f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
19664f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
19674f1b2e48SStefano Zampini     cum = 0;
19684f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
19694f1b2e48SStefano Zampini       PetscInt t;
19704f1b2e48SStefano Zampini 
19714f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
19724f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
19734f1b2e48SStefano Zampini           continue;
19744f1b2e48SStefano Zampini         }
19754f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
19764f1b2e48SStefano Zampini       }
19774f1b2e48SStefano Zampini       t = xadj_filtered[i];
19784f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
19794f1b2e48SStefano Zampini       cum += t;
19804f1b2e48SStefano Zampini     }
19814f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
19824f1b2e48SStefano Zampini   } else {
19834f1b2e48SStefano Zampini     xadj_filtered = NULL;
19844f1b2e48SStefano Zampini     adjncy_filtered = NULL;
19854f1b2e48SStefano Zampini   }
19864f1b2e48SStefano Zampini 
19874f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
19884f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
19894f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
19904f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
19914f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1992be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
19934f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
19944f1b2e48SStefano Zampini   if (xadj_filtered) {
19954f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
19964f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
19974f1b2e48SStefano Zampini   } else {
19984f1b2e48SStefano Zampini     graph->xadj = xadj;
19994f1b2e48SStefano Zampini     graph->adjncy = adjncy;
20004f1b2e48SStefano Zampini   }
20014f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
20024f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
20034f1b2e48SStefano Zampini   /* partial clean up */
20044f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
20054f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
20061cf9b237SStefano Zampini   if (A != B) {
20074f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
20084f1b2e48SStefano Zampini   }
20094f1b2e48SStefano Zampini 
20104f1b2e48SStefano Zampini   /* get back data */
20111cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
20121cf9b237SStefano Zampini   if (cc) {
20134f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
20144f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
20154f1b2e48SStefano 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);
20164f1b2e48SStefano Zampini     }
20174f1b2e48SStefano Zampini     *cc = cc_n;
20181cf9b237SStefano Zampini   }
20194f1b2e48SStefano Zampini   /* clean up graph */
20204f1b2e48SStefano Zampini   graph->xadj = 0;
20214f1b2e48SStefano Zampini   graph->adjncy = 0;
20224f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
20234f1b2e48SStefano Zampini   PetscFunctionReturn(0);
20244f1b2e48SStefano Zampini }
20254f1b2e48SStefano Zampini 
20264f1b2e48SStefano Zampini #undef __FUNCT__
20275408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
20285408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
20295408967cSStefano Zampini {
20305408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
20315408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2032dee84bffSStefano Zampini   IS             dirIS = NULL;
20334f1b2e48SStefano Zampini   PetscInt       i;
20345408967cSStefano Zampini   PetscErrorCode ierr;
20355408967cSStefano Zampini 
20365408967cSStefano Zampini   PetscFunctionBegin;
2037dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
20385408967cSStefano Zampini   if (zerodiag) {
20395408967cSStefano Zampini     Mat            A;
20405408967cSStefano Zampini     Vec            vec3_N;
20415408967cSStefano Zampini     PetscScalar    *vals;
20425408967cSStefano Zampini     const PetscInt *idxs;
2043d12d3064SStefano Zampini     PetscInt       nz,*count;
20445408967cSStefano Zampini 
20455408967cSStefano Zampini     /* p0 */
20465408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
20475408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
20485408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
20495408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
20504f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
20515408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
20525408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
20535408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
20545408967cSStefano Zampini     /* v_I */
20555408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
20565408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
20575408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
20585408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
20595408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
20605408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
20615408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
20625408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
20635408967cSStefano Zampini     if (dirIS) {
20645408967cSStefano Zampini       PetscInt n;
20655408967cSStefano Zampini 
20665408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
20675408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
20685408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
20695408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
20705408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
20715408967cSStefano Zampini     }
20725408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
20735408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
20745408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
20755408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2076669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
20775408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
20785408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
20799a962809SStefano 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]));
20805408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
20815408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2082d12d3064SStefano Zampini 
2083d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2084d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2085d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2086d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2087d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2088d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
20899a962809SStefano 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]);
2090d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2091d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
20925408967cSStefano Zampini   }
2093dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
20945408967cSStefano Zampini 
20955408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
20965408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
20974f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
20985408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
20994f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
21005408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2101f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2102f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
2103f2a566d8SStefano Zampini     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);CHKERRQ(ierr);
2104f2a566d8SStefano Zampini   }
21055408967cSStefano Zampini   PetscFunctionReturn(0);
21065408967cSStefano Zampini }
21075408967cSStefano Zampini 
21085408967cSStefano Zampini #undef __FUNCT__
2109339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
2110339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2111339f8db1SStefano Zampini {
2112339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
21134f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
2114b0f5fe93SStefano Zampini   PetscInt       nz,n;
21151f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
21164f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
2117339f8db1SStefano Zampini   PetscErrorCode ierr;
2118339f8db1SStefano Zampini 
2119339f8db1SStefano Zampini   PetscFunctionBegin;
21209f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
21219f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2122a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2123a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2124a3df083aSStefano Zampini   }
2125a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2126a3df083aSStefano Zampini   pcbddc->benign_n = 0;
21271ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
21284f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
21294f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
21304f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
21311ae86dd6SStefano Zampini      since the local Schur complements are already SPD
21324f1b2e48SStefano Zampini   */
21334f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
21344f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
213540fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
21364f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
21374f1b2e48SStefano Zampini 
21384f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
21394f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
21404f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
21414f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2142ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
214340fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
214440fa8d13SStefano Zampini     if (!sorted) {
214540fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
214640fa8d13SStefano Zampini     }
214740fa8d13SStefano Zampini   } else {
214840fa8d13SStefano Zampini     pressures = NULL;
214940fa8d13SStefano Zampini   }
215097d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
215197d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
215227b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
215397d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2154339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2155339f8db1SStefano Zampini   if (!sorted) {
2156339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2157339f8db1SStefano Zampini   }
2158339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
21594f1b2e48SStefano Zampini   if (!nz) {
21604f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
21614f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
216240fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
216340fa8d13SStefano Zampini   }
21644f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
21654f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
21664f1b2e48SStefano Zampini   zerodiag_subs = NULL;
21674f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
21681f4df5f7SStefano Zampini   n_interior_dofs = 0;
21691f4df5f7SStefano Zampini   interior_dofs = NULL;
21701f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
21711f4df5f7SStefano Zampini     PetscInt n,i,j;
21721f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
21731f4df5f7SStefano Zampini     PetscInt *iwork;
21741f4df5f7SStefano Zampini 
21751f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
21761f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
21771f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
21781f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
217990648384SStefano Zampini     for (i=1;i<n_neigh;i++)
21801f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
21811f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
21821f4df5f7SStefano Zampini     for (i=0;i<n;i++)
21831f4df5f7SStefano Zampini       if (!iwork[i])
21841f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
21851f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
21861f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
21871f4df5f7SStefano Zampini   }
21884f1b2e48SStefano Zampini   if (has_null_pressures) {
21894f1b2e48SStefano Zampini     IS             *subs;
21901f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
21911f4df5f7SStefano Zampini     const PetscInt *idxs;
21921f4df5f7SStefano Zampini     PetscScalar    *array;
21931f4df5f7SStefano Zampini     Vec            *work;
21941f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
21954f1b2e48SStefano Zampini 
21964f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
21974f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
21981f4df5f7SStefano 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) */
21991f4df5f7SStefano Zampini     if (pcbddc->current_level) {
22001f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
22011f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
22021f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
22031f4df5f7SStefano Zampini       /* work[0] = 1_p */
22041f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
22051f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
22061f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
22071f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
22081f4df5f7SStefano Zampini       /* work[0] = 1_v */
22091f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
22101f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
22111f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
22121f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
22131f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
22141f4df5f7SStefano Zampini     }
22154f1b2e48SStefano Zampini     if (nsubs > 1) {
22164f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
22174f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
22184f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
22194f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
22204f1b2e48SStefano Zampini         PetscInt               nl;
22214f1b2e48SStefano Zampini 
22224f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
22234f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
22244f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
22254f1b2e48SStefano Zampini         if (nl) {
22264f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
22274f1b2e48SStefano Zampini 
22281f4df5f7SStefano Zampini           if (pcbddc->current_level) {
22291f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
22301f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
22311f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
22321f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
22331f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
22341f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
22351f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
22361f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
22371f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
22381f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
22391f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
22401f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
22411f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
22421f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
22431f4df5f7SStefano Zampini                 break;
22441f4df5f7SStefano Zampini               }
22451f4df5f7SStefano Zampini             }
22461f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
22471f4df5f7SStefano Zampini           }
22481f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
22491f4df5f7SStefano Zampini             IS       t_bc;
22501f4df5f7SStefano Zampini             PetscInt nzb;
22511f4df5f7SStefano Zampini 
22521f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
22531f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
22541f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
22551f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
22561f4df5f7SStefano Zampini           }
22571f4df5f7SStefano Zampini           if (valid && pressures) {
22584f1b2e48SStefano Zampini             IS t_pressure_subs;
22594f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
22604f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
22614f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
22624f1b2e48SStefano Zampini           }
22634f1b2e48SStefano Zampini           if (valid) {
22644f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
22654f1b2e48SStefano Zampini             pcbddc->benign_n++;
22664f1b2e48SStefano Zampini           } else {
22674f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
22684f1b2e48SStefano Zampini           }
22694f1b2e48SStefano Zampini         }
22704f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
22714f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
22724f1b2e48SStefano Zampini       }
22734f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
22744f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
22751f4df5f7SStefano Zampini 
22761f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
22771f4df5f7SStefano Zampini         PetscInt nzb;
22781f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
22791f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
22801f4df5f7SStefano Zampini       }
22811f4df5f7SStefano Zampini       if (valid && pressures) {
22824f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
22834f1b2e48SStefano Zampini       }
22841f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
22851f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
22861f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
22871f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
22881f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
22891f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
22901f4df5f7SStefano Zampini               valid = PETSC_FALSE;
22911f4df5f7SStefano Zampini               break;
22921f4df5f7SStefano Zampini           }
22931f4df5f7SStefano Zampini         }
22941f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
22951f4df5f7SStefano Zampini       }
22964f1b2e48SStefano Zampini       if (valid) {
22974f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2298ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
22994f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
23004f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
23014f1b2e48SStefano Zampini       }
23024f1b2e48SStefano Zampini     }
23031f4df5f7SStefano Zampini     if (pcbddc->current_level) {
23041f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
23054f1b2e48SStefano Zampini     }
23061f4df5f7SStefano Zampini   }
23071f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
23084f1b2e48SStefano Zampini 
23094f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2310b9b0e38cSStefano Zampini     PetscInt n;
2311b9b0e38cSStefano Zampini 
23124f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
23134f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2314b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2315b9b0e38cSStefano Zampini     if (n) {
23164f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
23174f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
23184f1b2e48SStefano Zampini     }
2319b9b0e38cSStefano Zampini   }
23204f1b2e48SStefano Zampini 
23214f1b2e48SStefano Zampini   /* final check for null pressures */
23224f1b2e48SStefano Zampini   if (zerodiag && pressures) {
23234f1b2e48SStefano Zampini     PetscInt nz,np;
23244f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
23254f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
23264f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
23274f1b2e48SStefano Zampini   }
23284f1b2e48SStefano Zampini 
23294f1b2e48SStefano Zampini   if (recompute_zerodiag) {
23304f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
23314f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
23324f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
23334f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
23344f1b2e48SStefano Zampini     } else {
23354f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
23364f1b2e48SStefano Zampini 
23374f1b2e48SStefano Zampini       nzn = 0;
23384f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
23394f1b2e48SStefano Zampini         PetscInt ns;
23404f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
23414f1b2e48SStefano Zampini         nzn += ns;
23424f1b2e48SStefano Zampini       }
23434f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
23444f1b2e48SStefano Zampini       nzn = 0;
23454f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
23464f1b2e48SStefano Zampini         PetscInt ns,*idxs;
23474f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
23484f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
23494f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
23504f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
23514f1b2e48SStefano Zampini         nzn += ns;
23524f1b2e48SStefano Zampini       }
23534f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
23544f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
23554f1b2e48SStefano Zampini     }
23564f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
23574f1b2e48SStefano Zampini   }
23584f1b2e48SStefano Zampini 
2359669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2360a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2361a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2362a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2363a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2364a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2365a198735bSStefano Zampini 
23661f4df5f7SStefano Zampini     if (pressures) {
23671f4df5f7SStefano Zampini       isused = pressures;
23681f4df5f7SStefano Zampini     } else {
23691f4df5f7SStefano Zampini       isused = zerodiag;
23701f4df5f7SStefano Zampini     }
2371a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2372669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
23731ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
23741ae86dd6SStefano 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");
2375a198735bSStefano Zampini     n_isused = 0;
2376a198735bSStefano Zampini     if (isused) {
2377a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2378a198735bSStefano Zampini     }
2379a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2380a198735bSStefano Zampini     st = st-n_isused;
23811ae86dd6SStefano Zampini     if (n) {
2382a198735bSStefano Zampini       const PetscInt *gidxs;
2383a198735bSStefano Zampini 
2384a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2385a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2386a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2387a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2388a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2389a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
23901ae86dd6SStefano Zampini     } else {
2391a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2392a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2393a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2394a198735bSStefano Zampini     }
2395a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2396a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2397a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2398a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2399a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2400a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2401a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2402a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2403a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2404a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2405a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2406a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2407a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2408a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
24091ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24101ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24111ae86dd6SStefano Zampini   }
2412b3afcdbeSStefano Zampini 
2413b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
24144f1b2e48SStefano Zampini   if (has_null_pressures) {
24154f1b2e48SStefano Zampini     IS             zerodiagc;
24164f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
24174f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
24184f1b2e48SStefano Zampini 
24194f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2420339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2421339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2422339f8db1SStefano Zampini     /* local change of basis for pressures */
2423339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
242497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2425339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2426339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2427339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
24284f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
24294f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
24304f1b2e48SStefano Zampini       PetscInt nzs,j;
24314f1b2e48SStefano Zampini 
24324f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
24334f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
24344f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
24354f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
24364f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
24374f1b2e48SStefano Zampini     }
2438339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2439339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2440339f8db1SStefano Zampini     /* set identity on velocities */
2441339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2442339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2443339f8db1SStefano Zampini     }
24444f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
24454f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
24469f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
24474f1b2e48SStefano 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);
2448339f8db1SStefano Zampini     /* set change on pressures */
24494f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
24504f1b2e48SStefano Zampini       PetscScalar *array;
24514f1b2e48SStefano Zampini       PetscInt    nzs;
24524f1b2e48SStefano Zampini 
24534f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
24544f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
24554f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2456339f8db1SStefano Zampini         PetscScalar vals[2];
2457339f8db1SStefano Zampini         PetscInt    cols[2];
2458339f8db1SStefano Zampini 
2459339f8db1SStefano Zampini         cols[0] = idxs[i];
24604f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2461339f8db1SStefano Zampini         vals[0] = 1.;
2462b0f5fe93SStefano Zampini         vals[1] = 1.;
24634f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2464339f8db1SStefano Zampini       }
24654f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
24664f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
24674f1b2e48SStefano Zampini       array[nzs-1] = 1.;
24684f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
24694f1b2e48SStefano Zampini       /* store local idxs for p0 */
24704f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
24714f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2472339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
24734f1b2e48SStefano Zampini     }
2474339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2475339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2476a3df083aSStefano Zampini     /* project if needed */
2477a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
24781dd7afcfSStefano Zampini       Mat M;
24791dd7afcfSStefano Zampini 
24801dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2481339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
24821dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
24831dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2484a3df083aSStefano Zampini     }
24854f1b2e48SStefano Zampini     /* store global idxs for p0 */
24864f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2487339f8db1SStefano Zampini   }
2488ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
24894f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2490b0f5fe93SStefano Zampini 
2491b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2492b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
249327b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
249427b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2495339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2496339f8db1SStefano Zampini   PetscFunctionReturn(0);
2497339f8db1SStefano Zampini }
2498339f8db1SStefano Zampini 
2499339f8db1SStefano Zampini #undef __FUNCT__
2500015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2501015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2502efc2fbd9SStefano Zampini {
2503efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2504de9d7bd0SStefano Zampini   PetscScalar    *array;
2505efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2506efc2fbd9SStefano Zampini 
2507efc2fbd9SStefano Zampini   PetscFunctionBegin;
2508efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2509efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
25104f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2511efc2fbd9SStefano Zampini   }
2512de9d7bd0SStefano Zampini   if (get) {
2513efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
25144f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
25154f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2516efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2517de9d7bd0SStefano Zampini   } else {
2518de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2519de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2520de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2521de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2522efc2fbd9SStefano Zampini   }
2523efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2524efc2fbd9SStefano Zampini }
2525efc2fbd9SStefano Zampini 
2526efc2fbd9SStefano Zampini #undef __FUNCT__
2527c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2528c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2529c263805aSStefano Zampini {
2530c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2531c263805aSStefano Zampini   PetscErrorCode ierr;
2532c263805aSStefano Zampini 
2533c263805aSStefano Zampini   PetscFunctionBegin;
2534c263805aSStefano Zampini   /* TODO: add error checking
2535c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2536c263805aSStefano Zampini     - cannot push before pop.
25371c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2538c263805aSStefano Zampini   */
25394f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2540efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2541efc2fbd9SStefano Zampini   }
2542c263805aSStefano Zampini   if (pop) {
2543a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
25444f1b2e48SStefano Zampini       IS       is_p0;
25454f1b2e48SStefano Zampini       MatReuse reuse;
2546c263805aSStefano Zampini 
2547c263805aSStefano Zampini       /* extract B_0 */
25484f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
25494f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
25504f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
25514f1b2e48SStefano Zampini       }
25524f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
25534f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2554c263805aSStefano Zampini       /* remove rows and cols from local problem */
2555c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
255697d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
25574f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
25584f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2559a3df083aSStefano Zampini     } else {
2560a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2561a3df083aSStefano Zampini       PetscScalar *vals;
2562a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2563a3df083aSStefano Zampini 
2564a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2565a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2566a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
25670b5adadeSStefano Zampini         PetscInt *nnz;
2568a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2569a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2570a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2571331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2572331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2573331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2574331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2575331e053bSStefano Zampini         }
2576331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2577331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2578331e053bSStefano Zampini       }
2579a3df083aSStefano Zampini 
2580a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2581a3df083aSStefano Zampini         PetscScalar *array;
2582a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2583a3df083aSStefano Zampini 
2584a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2585a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2586a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2587a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2588a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2589a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2590a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2591a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2592a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2593a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2594a3df083aSStefano Zampini         cum = 0;
2595a3df083aSStefano Zampini         for (j=0;j<n;j++) {
259622db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2597a3df083aSStefano Zampini             vals[cum] = array[j];
2598a3df083aSStefano Zampini             idxs_ins[cum] = j;
2599a3df083aSStefano Zampini             cum++;
2600a3df083aSStefano Zampini           }
2601a3df083aSStefano Zampini         }
2602a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2603a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2604a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2605a3df083aSStefano Zampini       }
2606a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2607a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2608a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2609a3df083aSStefano Zampini     }
2610c263805aSStefano Zampini   } else { /* push */
2611a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
26124f1b2e48SStefano Zampini       PetscInt i;
26134f1b2e48SStefano Zampini 
26144f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
26154f1b2e48SStefano Zampini         PetscScalar *B0_vals;
26164f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
26174f1b2e48SStefano Zampini 
26184f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
26194f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
26207b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
26214f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
26224f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
26234f1b2e48SStefano Zampini       }
2624c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2625c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2626a3df083aSStefano Zampini     } else {
2627a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2628a3df083aSStefano Zampini     }
2629c263805aSStefano Zampini   }
2630c263805aSStefano Zampini   PetscFunctionReturn(0);
2631c263805aSStefano Zampini }
2632c263805aSStefano Zampini 
2633c263805aSStefano Zampini #undef __FUNCT__
2634b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
263508122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2636b1b3d7a2SStefano Zampini {
2637b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
263808122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
263908122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
264008122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
264108122e43SStefano Zampini   PetscScalar     *work,lwork;
264208122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
264308122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
264408122e43SStefano Zampini   PetscReal       *eigs,thresh;
26451b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2646f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
264708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
264808122e43SStefano Zampini   PetscReal       *rwork;
264908122e43SStefano Zampini #endif
2650b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2651b1b3d7a2SStefano Zampini 
2652b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2653b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2654af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2655af25d912SStefano 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)\n",sub_schurs->is_hermitian,sub_schurs->is_posdef);
265606a4e24aSStefano Zampini 
2657fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2658fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2659fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2660fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
26611575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2662fd14bc51SStefano Zampini   }
2663fd14bc51SStefano Zampini 
2664e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2665e496cd5dSStefano 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);
2666e496cd5dSStefano Zampini   }
2667e496cd5dSStefano Zampini 
266808122e43SStefano Zampini   /* max size of subsets */
266908122e43SStefano Zampini   mss = 0;
267008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
267108122e43SStefano Zampini     PetscInt subset_size;
2672862806e4SStefano Zampini 
267308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
267408122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
267508122e43SStefano Zampini   }
267608122e43SStefano Zampini 
267708122e43SStefano Zampini   /* min/max and threshold */
267808122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2679f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
268008122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2681f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2682f6f667cfSStefano Zampini   if (nmin) {
2683f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2684f6f667cfSStefano Zampini   }
268508122e43SStefano Zampini 
268608122e43SStefano Zampini   /* allocate lapack workspace */
268708122e43SStefano Zampini   cum = cum2 = 0;
268808122e43SStefano Zampini   maxneigs = 0;
268908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
269008122e43SStefano Zampini     PetscInt n,subset_size;
2691f6f667cfSStefano Zampini 
269208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
269308122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
26949162d606SStefano Zampini     cum += subset_size;
26959162d606SStefano Zampini     cum2 += subset_size*n;
269608122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
269708122e43SStefano Zampini   }
269808122e43SStefano Zampini   if (mss) {
26999ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
270008122e43SStefano Zampini       PetscBLASInt B_itype = 1;
270108122e43SStefano Zampini       PetscBLASInt B_N = mss;
27024c6709b3SStefano Zampini       PetscReal    zero = 0.0;
27034c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
270408122e43SStefano Zampini 
270508122e43SStefano Zampini       B_lwork = -1;
270608122e43SStefano Zampini       S = NULL;
270708122e43SStefano Zampini       St = NULL;
2708a58a30b4SStefano Zampini       eigs = NULL;
2709a58a30b4SStefano Zampini       eigv = NULL;
2710a58a30b4SStefano Zampini       B_iwork = NULL;
2711a58a30b4SStefano Zampini       B_ifail = NULL;
2712d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2713d1710679SStefano Zampini       rwork = NULL;
2714d1710679SStefano Zampini #endif
27158bec7fa6SStefano Zampini       thresh = 1.0;
271608122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
271708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
271808122e43SStefano 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));
271908122e43SStefano Zampini #else
272008122e43SStefano 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));
272108122e43SStefano Zampini #endif
272208122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
272308122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
272408122e43SStefano Zampini     } else {
272508122e43SStefano Zampini         /* TODO */
272608122e43SStefano Zampini     }
272708122e43SStefano Zampini   } else {
272808122e43SStefano Zampini     lwork = 0;
272908122e43SStefano Zampini   }
273008122e43SStefano Zampini 
273108122e43SStefano Zampini   nv = 0;
2732d62866d3SStefano 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) */
2733d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
273408122e43SStefano Zampini   }
27354c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2736f6f667cfSStefano Zampini   if (allocated_S_St) {
2737f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2738f6f667cfSStefano Zampini   }
2739f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
274008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
274108122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
274208122e43SStefano Zampini #endif
27439162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
27449162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
27459162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
274608122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
27479162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
274808122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
274908122e43SStefano Zampini 
275008122e43SStefano Zampini   maxneigs = 0;
275172b8c272SStefano Zampini   cum = cumarray = 0;
27529162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
27539162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2754d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
275508122e43SStefano Zampini     const PetscInt *idxs;
275608122e43SStefano Zampini 
2757d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
275808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
275908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
276008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
276108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
27629162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
27639162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
276408122e43SStefano Zampini     }
2765d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
276608122e43SStefano Zampini   }
276708122e43SStefano Zampini 
276808122e43SStefano Zampini   if (mss) { /* multilevel */
276908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
277008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
277108122e43SStefano Zampini   }
277208122e43SStefano Zampini 
2773ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
277408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
277508122e43SStefano Zampini     const PetscInt *idxs;
27769d54b7f4SStefano Zampini     PetscReal      upper,lower;
2777862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
277808122e43SStefano Zampini     PetscBLASInt   B_N;
2779aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
278008122e43SStefano Zampini 
27819d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
27829d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
27839d54b7f4SStefano Zampini       lower = thresh;
27849d54b7f4SStefano Zampini     } else {
27859d54b7f4SStefano Zampini       upper = 1./thresh;
27869d54b7f4SStefano Zampini       lower = 0.;
27879d54b7f4SStefano Zampini     }
2788862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2789ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2790f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2791f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
27929ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2793aff50787SStefano Zampini         PetscInt j,k;
2794aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2795aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2796aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
279708122e43SStefano Zampini         }
279808122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2799aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2800aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2801aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2802aff50787SStefano Zampini           }
280308122e43SStefano Zampini         }
280408122e43SStefano Zampini       } else {
280508122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
280608122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
280708122e43SStefano Zampini       }
28088bec7fa6SStefano Zampini     } else {
2809f6f667cfSStefano Zampini       S = Sarray + cumarray;
2810f6f667cfSStefano Zampini       St = Starray + cumarray;
28118bec7fa6SStefano Zampini     }
2812aff50787SStefano Zampini     /* see if we can save some work */
2813b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2814aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2815aff50787SStefano Zampini     }
2816aff50787SStefano Zampini 
2817b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2818aff50787SStefano Zampini       B_neigs = 0;
2819aff50787SStefano Zampini     } else {
28209ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
282108122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2822f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
28234c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
28249552c7c7SStefano Zampini         PetscInt     nmin_s;
2825b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
282608122e43SStefano Zampini 
2827fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2828*eee23b56SStefano 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]]);
2829fd14bc51SStefano Zampini         }
2830d16cbb6bSStefano Zampini 
2831b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2832b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2833b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2834b7ab4a40SStefano Zampini         }
2835b7ab4a40SStefano Zampini 
283608122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2837b7ab4a40SStefano Zampini         if (compute_range) {
2838d16cbb6bSStefano Zampini 
2839d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
284008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
28419d54b7f4SStefano 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));
284208122e43SStefano Zampini #else
28439d54b7f4SStefano 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));
284408122e43SStefano Zampini #endif
2845b7ab4a40SStefano Zampini         } else if (!same_data) {
2846d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2847d16cbb6bSStefano Zampini           B_IL = 1;
2848d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
28499d54b7f4SStefano 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));
2850d16cbb6bSStefano Zampini #else
28519d54b7f4SStefano 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));
2852d16cbb6bSStefano Zampini #endif
2853b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
2854b7ab4a40SStefano Zampini           PetscInt k;
2855b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2856b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2857b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2858b7ab4a40SStefano Zampini           nmin = nmax;
2859b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2860b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2861b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2862b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2863b7ab4a40SStefano Zampini           }
2864d16cbb6bSStefano Zampini         }
286508122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
286608122e43SStefano Zampini         if (B_ierr) {
28676c4ed002SBarry 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);
28686c4ed002SBarry 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);
28696c4ed002SBarry 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);
287008122e43SStefano Zampini         }
287108122e43SStefano Zampini 
287208122e43SStefano Zampini         if (B_neigs > nmax) {
2873fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2874fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2875fd14bc51SStefano Zampini           }
28769d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
287708122e43SStefano Zampini           B_neigs = nmax;
287808122e43SStefano Zampini         }
287908122e43SStefano Zampini 
28809552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
28819552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
288208122e43SStefano Zampini           PetscBLASInt B_neigs2;
288308122e43SStefano Zampini 
28849d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2885f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
28869d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
28879d54b7f4SStefano Zampini           } else {
28889d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
28899d54b7f4SStefano Zampini             B_IU = nmin_s;
28909d54b7f4SStefano Zampini           }
2891fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2892fd14bc51SStefano 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);
2893fd14bc51SStefano Zampini           }
28949ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
28951ae86dd6SStefano Zampini             PetscInt j,k;
289608122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
28971ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
28981ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
28991ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
290008122e43SStefano Zampini               }
290108122e43SStefano Zampini             }
290208122e43SStefano Zampini           } else {
290308122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
290408122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
290508122e43SStefano Zampini           }
290608122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
290708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29089d54b7f4SStefano 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));
290908122e43SStefano Zampini #else
29109d54b7f4SStefano 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));
291108122e43SStefano Zampini #endif
291208122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
291308122e43SStefano Zampini           B_neigs += B_neigs2;
291408122e43SStefano Zampini         }
291508122e43SStefano Zampini         if (B_ierr) {
29166c4ed002SBarry 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);
29176c4ed002SBarry 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);
29186c4ed002SBarry 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);
291908122e43SStefano Zampini         }
2920fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2921ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
292208122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
292308122e43SStefano Zampini             if (eigs[j] == 0.0) {
2924ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
292508122e43SStefano Zampini             } else {
29269d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2927ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
29289d54b7f4SStefano Zampini               } else {
29299d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
29309d54b7f4SStefano Zampini               }
2931fd14bc51SStefano Zampini             }
293208122e43SStefano Zampini           }
293308122e43SStefano Zampini         }
293408122e43SStefano Zampini       } else {
293508122e43SStefano Zampini           /* TODO */
293608122e43SStefano Zampini       }
2937aff50787SStefano Zampini     }
29386c3e6151SStefano Zampini     /* change the basis back to the original one */
29396c3e6151SStefano Zampini     if (sub_schurs->change) {
294072b8c272SStefano Zampini       Mat change,phi,phit;
29416c3e6151SStefano Zampini 
29426c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
29436c3e6151SStefano Zampini         PetscInt ii;
29446c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
29456c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
29466c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2947684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2948684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2949684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2950684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2951684229deSStefano Zampini #else
29526c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2953684229deSStefano Zampini #endif
29546c3e6151SStefano Zampini           }
29556c3e6151SStefano Zampini         }
29566c3e6151SStefano Zampini       }
295772b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
29586c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
295972b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
29606c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
29616c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
29626c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
29636c3e6151SStefano Zampini     }
29648bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
29658bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
29669162d606SStefano Zampini     if (B_neigs) {
29679162d606SStefano 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);
2968fd14bc51SStefano Zampini 
2969fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
29709552c7c7SStefano Zampini         PetscInt ii;
29719552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2972ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
29739552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2974ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2975ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2976ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2977ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2978ac47001eSStefano Zampini #else
2979ac47001eSStefano 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);
2980ac47001eSStefano Zampini #endif
29819552c7c7SStefano Zampini           }
29829552c7c7SStefano Zampini         }
2983fd14bc51SStefano Zampini       }
29849162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
29859162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
29869162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
29879162d606SStefano Zampini       cum++;
298808122e43SStefano Zampini     }
298908122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
299008122e43SStefano Zampini     /* shift for next computation */
299108122e43SStefano Zampini     cumarray += subset_size*subset_size;
299208122e43SStefano Zampini   }
2993fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2994fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2995fd14bc51SStefano Zampini   }
299608122e43SStefano Zampini 
299708122e43SStefano Zampini   if (mss) {
299808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
299908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3000f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3001f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3002f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
300308122e43SStefano Zampini   }
3004f6f667cfSStefano Zampini   if (allocated_S_St) {
3005f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3006f6f667cfSStefano Zampini   }
3007f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
300808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
300908122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
301008122e43SStefano Zampini #endif
301108122e43SStefano Zampini   if (pcbddc->dbg_flag) {
30121b968477SStefano Zampini     PetscInt maxneigs_r;
3013b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
30149b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
301508122e43SStefano Zampini   }
301608122e43SStefano Zampini   PetscFunctionReturn(0);
301708122e43SStefano Zampini }
3018b1b3d7a2SStefano Zampini 
3019674ae819SStefano Zampini #undef __FUNCT__
3020c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
3021c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3022c8587f34SStefano Zampini {
30238629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3024c8587f34SStefano Zampini   PetscErrorCode ierr;
3025c8587f34SStefano Zampini 
3026c8587f34SStefano Zampini   PetscFunctionBegin;
3027f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
30285e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3029c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3030c8587f34SStefano Zampini 
3031684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
30320fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3033684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3034c8587f34SStefano Zampini 
30358629588bSStefano Zampini   /*
30368629588bSStefano Zampini      Setup local correction and local part of coarse basis.
30378629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
30388629588bSStefano Zampini   */
303947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
30408629588bSStefano Zampini 
30418629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
30428629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
30438629588bSStefano Zampini 
30448629588bSStefano Zampini   /* free */
30458629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3046c8587f34SStefano Zampini   PetscFunctionReturn(0);
3047c8587f34SStefano Zampini }
3048c8587f34SStefano Zampini 
3049c8587f34SStefano Zampini #undef __FUNCT__
3050674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
3051674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3052674ae819SStefano Zampini {
3053674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3054674ae819SStefano Zampini   PetscErrorCode ierr;
3055674ae819SStefano Zampini 
3056674ae819SStefano Zampini   PetscFunctionBegin;
3057674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
305830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3059674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3060785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3061674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3062f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3063f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3064785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
306563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
306663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3067674ae819SStefano Zampini   PetscFunctionReturn(0);
3068674ae819SStefano Zampini }
3069674ae819SStefano Zampini 
3070674ae819SStefano Zampini #undef __FUNCT__
3071674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
3072674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3073674ae819SStefano Zampini {
3074674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
30754f1b2e48SStefano Zampini   PetscInt       i;
3076674ae819SStefano Zampini   PetscErrorCode ierr;
3077674ae819SStefano Zampini 
3078674ae819SStefano Zampini   PetscFunctionBegin;
30791e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
30801e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3081a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3082b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3083674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
308416909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
30851dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3086674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3087669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3088fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
3089a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
3090674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
30914f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
30924f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
30934f1b2e48SStefano Zampini   }
30944f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3095b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
3096b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
3097b334f244SStefano Zampini   }
3098c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
30998af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3100674ae819SStefano Zampini   PetscFunctionReturn(0);
3101674ae819SStefano Zampini }
3102674ae819SStefano Zampini 
3103674ae819SStefano Zampini #undef __FUNCT__
3104674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
3105674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3106674ae819SStefano Zampini {
3107674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3108674ae819SStefano Zampini   PetscErrorCode ierr;
3109674ae819SStefano Zampini 
3110674ae819SStefano Zampini   PetscFunctionBegin;
3111674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
311258da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3113ca92afb2SStefano Zampini     PetscScalar *array;
311406656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
311506656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
311658da7f69SStefano Zampini   }
3117674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3118674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
311915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
312015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3121674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3122674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3123674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
312406656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3125674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3126674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
31278ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3128674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3129674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3130674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
3131f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
3132f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
3133f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
3134f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3135727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
31360e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3137f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
313870cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
313981d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
31400369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
31411dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
31424f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
31438b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3144ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3145ca92afb2SStefano Zampini     PetscInt i;
3146ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3147ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3148ca92afb2SStefano Zampini     }
3149ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3150ca92afb2SStefano Zampini   }
31514f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3152674ae819SStefano Zampini   PetscFunctionReturn(0);
3153674ae819SStefano Zampini }
3154674ae819SStefano Zampini 
3155674ae819SStefano Zampini #undef __FUNCT__
3156f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
3157f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
31586bfb1811SStefano Zampini {
31596bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
31606bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
31616bfb1811SStefano Zampini   VecType        impVecType;
31624f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
31636bfb1811SStefano Zampini   PetscErrorCode ierr;
31646bfb1811SStefano Zampini 
31656bfb1811SStefano Zampini   PetscFunctionBegin;
31666c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
3167e7b262bdSStefano Zampini   /* get sizes */
31684f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3169b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
31706bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3171e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3172e7b262bdSStefano Zampini   /* R nodes */
3173e7b262bdSStefano Zampini   old_size = -1;
3174e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3175e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3176e7b262bdSStefano Zampini   }
3177e7b262bdSStefano Zampini   if (n_R != old_size) {
3178e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3179e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
31806bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
31816bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
31826bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
31836bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3184e7b262bdSStefano Zampini   }
3185e7b262bdSStefano Zampini   /* local primal dofs */
3186e7b262bdSStefano Zampini   old_size = -1;
3187e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3188e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3189e7b262bdSStefano Zampini   }
3190e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3191e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
319283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3193e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
31946bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3195e7b262bdSStefano Zampini   }
3196e7b262bdSStefano Zampini   /* local explicit constraints */
3197e7b262bdSStefano Zampini   old_size = -1;
3198e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3199e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3200e7b262bdSStefano Zampini   }
3201e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3202e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
320383b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
320483b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
320583b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
320683b7ccabSStefano Zampini   }
32076bfb1811SStefano Zampini   PetscFunctionReturn(0);
32086bfb1811SStefano Zampini }
32096bfb1811SStefano Zampini 
32106bfb1811SStefano Zampini #undef __FUNCT__
321147f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
321247f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
321388ebb749SStefano Zampini {
321425084f0cSStefano Zampini   PetscErrorCode  ierr;
321525084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
321688ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
321788ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3218d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
321925084f0cSStefano Zampini   /* submatrices of local problem */
322080677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
322106656605SStefano Zampini   /* submatrices of local coarse problem */
322206656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
322325084f0cSStefano Zampini   /* working matrices */
322406656605SStefano Zampini   Mat             C_CR;
322525084f0cSStefano Zampini   /* additional working stuff */
322606656605SStefano Zampini   PC              pc_R;
32274f1b2e48SStefano Zampini   Mat             F;
32285cbda25cSStefano Zampini   Vec             dummy_vec;
3229a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
323025084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
323106656605SStefano Zampini   PetscScalar     *work;
323206656605SStefano Zampini   PetscInt        *idx_V_B;
3233ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
323406656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3235ffd830a3SStefano Zampini 
323625084f0cSStefano Zampini   /* some shortcuts to scalars */
323706656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
323888ebb749SStefano Zampini 
323988ebb749SStefano Zampini   PetscFunctionBegin;
32409a962809SStefano 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");
3241ffd830a3SStefano Zampini 
3242ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3243b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
32444f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3245b371cd4fSStefano Zampini   n_B = pcis->n_B;
3246b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
324788ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
324888ebb749SStefano Zampini 
324988ebb749SStefano Zampini   /* vertices in boundary numbering */
3250785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
32510e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
32526c4ed002SBarry 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);
325388ebb749SStefano Zampini 
325406656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3255019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
325606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
325706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
325806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
325906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
326006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
326106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
326206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
326306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
326406656605SStefano Zampini 
326506656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
326606656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
326706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
326806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
326906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3270ffd830a3SStefano Zampini   lda_rhs = n_R;
3271a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
327206656605SStefano Zampini   if (isLU || isILU || isCHOL) {
327306656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3274b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3275df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3276d62866d3SStefano Zampini     MatFactorType      type;
3277d62866d3SStefano Zampini 
3278df4d28bfSStefano Zampini     F = reuse_solver->F;
32796816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3280d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3281ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
328222db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
328306656605SStefano Zampini   } else {
328406656605SStefano Zampini     F = NULL;
328506656605SStefano Zampini   }
328606656605SStefano Zampini 
3287ffd830a3SStefano Zampini   /* allocate workspace */
3288ffd830a3SStefano Zampini   n = 0;
3289ffd830a3SStefano Zampini   if (n_constraints) {
3290ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3291ffd830a3SStefano Zampini   }
3292ffd830a3SStefano Zampini   if (n_vertices) {
3293ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3294ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3295ffd830a3SStefano Zampini   }
3296ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3297ffd830a3SStefano Zampini 
32985cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
32995cbda25cSStefano Zampini   dummy_vec = NULL;
33005cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
33015cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
33025cbda25cSStefano Zampini   }
33035cbda25cSStefano Zampini 
330488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
330588ebb749SStefano Zampini   if (n_constraints) {
330672b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
330706656605SStefano Zampini     IS          is_aux;
330880677318SStefano Zampini     PetscScalar *array,*array2;
330906656605SStefano Zampini 
3310f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
331180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
331288ebb749SStefano Zampini 
331325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
331425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
33158ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
331672b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
331788ebb749SStefano Zampini 
331880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
331980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3320ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
332188ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
332206656605SStefano Zampini       const PetscScalar *row_cmat_values;
332306656605SStefano Zampini       const PetscInt    *row_cmat_indices;
332406656605SStefano Zampini       PetscInt          size_of_constraint,j;
332588ebb749SStefano Zampini 
332606656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
332706656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
3328ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
332906656605SStefano Zampini       }
333006656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
333106656605SStefano Zampini     }
3332ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
333306656605SStefano Zampini     if (F) {
333406656605SStefano Zampini       Mat B;
333506656605SStefano Zampini 
3336ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
3337a3df083aSStefano Zampini       if (need_benign_correction) {
3338df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3339a3df083aSStefano Zampini 
334072b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
334172b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3342a3df083aSStefano Zampini       }
334380677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
3344a3df083aSStefano Zampini       if (need_benign_correction) {
3345a3df083aSStefano Zampini         PetscScalar        *marr;
3346df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3347a3df083aSStefano Zampini 
3348a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
33495cbda25cSStefano Zampini         if (lda_rhs != n_R) {
33505cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
33515cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
33525cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
33535cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
33545cbda25cSStefano Zampini           }
33555cbda25cSStefano Zampini         } else {
3356a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3357a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
33585cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3359a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3360a3df083aSStefano Zampini           }
33615cbda25cSStefano Zampini         }
3362a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3363a3df083aSStefano Zampini       }
336406656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
336506656605SStefano Zampini     } else {
336680677318SStefano Zampini       PetscScalar *marr;
336780677318SStefano Zampini 
336880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
336906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3370ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3371ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
337206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
337306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
337406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
337506656605SStefano Zampini       }
337680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
337706656605SStefano Zampini     }
337880677318SStefano Zampini     if (!pcbddc->switch_static) {
337980677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
338080677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
338180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
338280677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3383ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
338480677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
338580677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338680677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338780677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
338880677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
338980677318SStefano Zampini       }
339080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
339180677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
339272b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
339380677318SStefano Zampini     } else {
3394ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3395ffd830a3SStefano Zampini         IS dummy;
3396ffd830a3SStefano Zampini 
3397ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
339872b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3399ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3400ffd830a3SStefano Zampini       } else {
340180677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
340280677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3403ffd830a3SStefano Zampini       }
340425084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
340580677318SStefano Zampini     }
340680677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
340780677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
340880677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
340906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
341006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
341180677318SStefano Zampini     if (isCHOL) {
341280677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
341380677318SStefano Zampini     } else {
341425084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
341580677318SStefano Zampini     }
341680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
341706656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
341825084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
341925084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
342025084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
342180677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
342272b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
342372b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
342406656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
342506656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3426f4ddd8eeSStefano Zampini   }
3427fc227af8SStefano Zampini 
3428fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
342988ebb749SStefano Zampini   if (n_vertices) {
343006656605SStefano Zampini     IS is_aux;
34313a50541eSStefano Zampini 
3432b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
34336816873aSStefano Zampini       IS tis;
34346816873aSStefano Zampini 
34356816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
34366816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
34376816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
34386816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
34396816873aSStefano Zampini     } else {
34403a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
34416816873aSStefano Zampini     }
34429577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
34439577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
344404708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
344525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
344688ebb749SStefano Zampini   }
344788ebb749SStefano Zampini 
344888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3449f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
345006656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
345106656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
345206656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
345306656605SStefano Zampini     }
3454f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
345506656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
345606656605SStefano Zampini       PetscScalar *marray;
345706656605SStefano Zampini 
345806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
345906656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3460f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3461f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3462f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3463f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3464f4ddd8eeSStefano Zampini     }
3465f4ddd8eeSStefano Zampini   }
346606656605SStefano Zampini 
3467f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
346806656605SStefano Zampini     PetscScalar *marray;
346988ebb749SStefano Zampini 
347006656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
34718eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
347206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
347388ebb749SStefano Zampini     }
34743301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
347506656605SStefano Zampini       n *= 2;
347688ebb749SStefano Zampini     }
347706656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
347806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
347906656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
34808eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
348106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
348206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
348388ebb749SStefano Zampini     }
34843301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
348506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
34868eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
348706656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
348806656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
348988ebb749SStefano Zampini       }
349088ebb749SStefano Zampini     } else {
3491c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3492c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
34931b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3494c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3495c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3496c0553b1fSStefano Zampini       }
349788ebb749SStefano Zampini     }
349806656605SStefano Zampini   }
3499019a44ceSStefano Zampini 
350006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
35014f1b2e48SStefano Zampini   p0_lidx_I = NULL;
35024f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3503d12edf2fSStefano Zampini     const PetscInt *idxs;
3504d12edf2fSStefano Zampini 
3505d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
35064f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
35074f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
35084f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
35094f1b2e48SStefano Zampini     }
3510d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3511d12edf2fSStefano Zampini   }
3512d16cbb6bSStefano Zampini 
351306656605SStefano Zampini   /* vertices */
351406656605SStefano Zampini   if (n_vertices) {
351516f15bc4SStefano Zampini 
3516af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
351704708bb6SStefano Zampini 
351816f15bc4SStefano Zampini     if (n_R) {
351914393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
352006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
352116f15bc4SStefano Zampini       PetscScalar  *x,*y;
352204708bb6SStefano Zampini       PetscBool    isseqaij;
352306656605SStefano Zampini 
352421eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
352514393ed6SStefano Zampini       if (need_benign_correction) {
352614393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
352714393ed6SStefano Zampini         IS                     is_p0;
352814393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
352914393ed6SStefano Zampini 
353014393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
353114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
353214393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3533af25d912SStefano 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);
353414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
353514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
353614393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
353714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
353814393ed6SStefano Zampini       }
353914393ed6SStefano Zampini 
3540ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3541af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3542ffd830a3SStefano Zampini       } else {
3543ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3544ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3545ca92afb2SStefano Zampini         PetscInt       n;
3546ca92afb2SStefano Zampini         PetscBool      flg_row;
3547ffd830a3SStefano Zampini 
3548ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3549ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
35509d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3551ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3552ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3553ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3554ca92afb2SStefano Zampini           PetscInt j;
3555ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3556ffd830a3SStefano Zampini         }
3557ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3558ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3559ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3560ffd830a3SStefano Zampini       }
3561ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3562a3df083aSStefano Zampini       if (need_benign_correction) {
3563df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3564a3df083aSStefano Zampini         PetscScalar        *marr;
3565a3df083aSStefano Zampini 
3566a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
356714393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
356814393ed6SStefano Zampini 
356914393ed6SStefano Zampini                | 0 0  0 | (V)
357014393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
357114393ed6SStefano Zampini                | 0 0 -1 | (p0)
357214393ed6SStefano Zampini 
357314393ed6SStefano Zampini         */
3574df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
357514393ed6SStefano Zampini           const PetscScalar *vals;
357614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
357714393ed6SStefano Zampini           PetscInt          n,j,nz;
357814393ed6SStefano Zampini 
3579df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3580df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
358114393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
358214393ed6SStefano Zampini           for (j=0;j<n;j++) {
358314393ed6SStefano Zampini             PetscScalar val = vals[j];
358414393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
358514393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
358614393ed6SStefano Zampini           }
358714393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3588df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
358914393ed6SStefano Zampini         }
359072b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
359172b8c272SStefano Zampini       }
359272b8c272SStefano Zampini       if (F) {
359314393ed6SStefano Zampini         /* need to correct the rhs */
359472b8c272SStefano Zampini         if (need_benign_correction) {
359572b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
359672b8c272SStefano Zampini           PetscScalar        *marr;
359772b8c272SStefano Zampini 
359872b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
35995cbda25cSStefano Zampini           if (lda_rhs != n_R) {
36005cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
36015cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
36025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
36035cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
36045cbda25cSStefano Zampini             }
36055cbda25cSStefano Zampini           } else {
3606a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3607a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
36085cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3609a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3610a3df083aSStefano Zampini             }
36115cbda25cSStefano Zampini           }
3612a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3613a3df083aSStefano Zampini         }
361406656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
361514393ed6SStefano Zampini         /* need to correct the solution */
3616a3df083aSStefano Zampini         if (need_benign_correction) {
3617df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3618a3df083aSStefano Zampini           PetscScalar        *marr;
3619a3df083aSStefano Zampini 
3620a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
36215cbda25cSStefano Zampini           if (lda_rhs != n_R) {
36225cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
36235cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
36245cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
36255cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
36265cbda25cSStefano Zampini             }
36275cbda25cSStefano Zampini           } else {
3628a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3629a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
36305cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3631a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3632a3df083aSStefano Zampini             }
36335cbda25cSStefano Zampini           }
3634a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3635a3df083aSStefano Zampini         }
363606656605SStefano Zampini       } else {
363706656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
363806656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3639ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3640ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
364106656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
364206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
364306656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
364406656605SStefano Zampini         }
364506656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
364606656605SStefano Zampini       }
364780677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3648ffd830a3SStefano Zampini       /* S_VV and S_CV */
364906656605SStefano Zampini       if (n_constraints) {
365006656605SStefano Zampini         Mat B;
365180677318SStefano Zampini 
3652ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
365380677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3654ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3655ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
365680677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
365780677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
365880677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
365980677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
366080677318SStefano Zampini         }
3661ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
366280677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
366380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3664ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
366580677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
366606656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3667ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3668ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
366906656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
367006656605SStefano Zampini       }
367104708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
367204708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3673511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
367404708bb6SStefano Zampini       }
3675ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3676ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3677ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3678ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3679ffd830a3SStefano Zampini       }
368006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
368114393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
368214393ed6SStefano Zampini       if (need_benign_correction) {
3683df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
368414393ed6SStefano Zampini         PetscScalar      *marr,*sums;
368514393ed6SStefano Zampini 
368614393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
3687f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
3688df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
368914393ed6SStefano Zampini           const PetscScalar *vals;
369014393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
369114393ed6SStefano Zampini           PetscInt          n,j,nz;
369214393ed6SStefano Zampini 
3693df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3694df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
369514393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
369614393ed6SStefano Zampini             PetscInt k;
369714393ed6SStefano Zampini             sums[j] = 0.;
369814393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
369914393ed6SStefano Zampini           }
370014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
370114393ed6SStefano Zampini           for (j=0;j<n;j++) {
370214393ed6SStefano Zampini             PetscScalar val = vals[j];
370314393ed6SStefano Zampini             PetscInt k;
370414393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
370514393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
370614393ed6SStefano Zampini             }
370714393ed6SStefano Zampini           }
370814393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3709df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
371014393ed6SStefano Zampini         }
371114393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
3712f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
371314393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
371414393ed6SStefano Zampini       }
371580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
371606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
371706656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
371806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
371906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
372006656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
372106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
372206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3723d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3724019a44ceSStefano Zampini     } else {
3725d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3726d16cbb6bSStefano Zampini     }
372721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3728d16cbb6bSStefano Zampini 
372906656605SStefano Zampini     /* coarse basis functions */
373006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
373116f15bc4SStefano Zampini       PetscScalar *y;
373216f15bc4SStefano Zampini 
3733ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
373406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
373506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
373606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
373706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
373806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
373906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
374006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
374106656605SStefano Zampini 
374206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
37434f1b2e48SStefano Zampini         PetscInt j;
37444f1b2e48SStefano Zampini 
374506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
374606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
374706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
374806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
374906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
37504f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
375106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
375206656605SStefano Zampini       }
375306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
375406656605SStefano Zampini     }
375504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
375604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
375706656605SStefano Zampini   }
37585cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
375906656605SStefano Zampini 
376006656605SStefano Zampini   if (n_constraints) {
376106656605SStefano Zampini     Mat B;
376206656605SStefano Zampini 
3763ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
376406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
376580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
376606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
376706656605SStefano Zampini     if (n_vertices) {
376880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
376980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
377080677318SStefano Zampini       } else {
377180677318SStefano Zampini         Mat S_VCt;
377280677318SStefano Zampini 
3773ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3774ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
377572b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3776ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3777ffd830a3SStefano Zampini         }
377880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
377980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
378080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
378180677318SStefano Zampini       }
378206656605SStefano Zampini     }
378306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
378406656605SStefano Zampini     /* coarse basis functions */
378506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
378606656605SStefano Zampini       PetscScalar *y;
378706656605SStefano Zampini 
3788ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
378906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
379006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
379106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
379206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
379306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
379406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
379506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
37964f1b2e48SStefano Zampini         PetscInt j;
37974f1b2e48SStefano Zampini 
379806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
379906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
380006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
380106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
380206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
38034f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
380406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
380506656605SStefano Zampini       }
380606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
380706656605SStefano Zampini     }
380806656605SStefano Zampini   }
380980677318SStefano Zampini   if (n_constraints) {
381080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
381180677318SStefano Zampini   }
38124f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
381372b8c272SStefano Zampini 
381472b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
381572b8c272SStefano Zampini   if (pcbddc->benign_n) {
381672b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
381772b8c272SStefano Zampini     IS          is_dummy;
381872b8c272SStefano Zampini     PetscScalar *data;
381972b8c272SStefano Zampini     PetscInt    j;
382072b8c272SStefano Zampini 
382172b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
382272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
382372b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
382472b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
382586c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
382672b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
382772b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
382872b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
382972b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
383072b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
383172b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
383272b8c272SStefano Zampini       }
383372b8c272SStefano Zampini     }
383472b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
383572b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
383672b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
383772b8c272SStefano Zampini   }
3838019a44ceSStefano Zampini 
383906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
38403301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3841ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3842ffd830a3SStefano Zampini     PetscScalar *marray;
384306656605SStefano Zampini 
384406656605SStefano Zampini     if (n_constraints) {
3845ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
384606656605SStefano Zampini 
3847af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
384806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3849ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
385016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
385106656605SStefano Zampini       if (n_vertices) {
3852ffd830a3SStefano Zampini         Mat S_VCT;
385306656605SStefano Zampini 
385406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3855ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
385616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
385706656605SStefano Zampini       }
3858ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
38595b782168SStefano Zampini     } else {
38605b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
386106656605SStefano Zampini     }
386216f15bc4SStefano Zampini     if (n_vertices && n_R) {
3863ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3864ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3865ffd830a3SStefano Zampini       PetscInt       n;
3866ffd830a3SStefano Zampini       PetscBool      flg_row;
386706656605SStefano Zampini 
3868ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3869af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3870ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3871ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3872ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3873ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3874ffd830a3SStefano Zampini         PetscInt j;
3875ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3876ffd830a3SStefano Zampini       }
3877ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3878ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3879ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
388006656605SStefano Zampini     }
388106656605SStefano Zampini 
3882ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3883ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3884ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3885ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3886ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
388706656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
388806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
388906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
389006656605SStefano Zampini     }
3891ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
38925b782168SStefano Zampini     if (B_C) {
3893ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3894ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3895ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3896ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3897ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3898ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3899ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
390006656605SStefano Zampini       }
3901ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
39025b782168SStefano Zampini     }
390306656605SStefano Zampini     /* coarse basis functions */
390406656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
390506656605SStefano Zampini       PetscScalar *y;
390606656605SStefano Zampini 
3907ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
390806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
390906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
391006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
391106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
391206656605SStefano Zampini       if (i<n_vertices) {
391306656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
391406656605SStefano Zampini       }
391506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
391606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
391706656605SStefano Zampini 
391806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
391906656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
392006656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
392106656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
392206656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
392306656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
392406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
392506656605SStefano Zampini       }
392606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
392706656605SStefano Zampini     }
3928ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3929ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
393006656605SStefano Zampini   }
3931d62866d3SStefano Zampini   /* free memory */
393288ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
393306656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
393406656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
393506656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
393606656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3937d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3938d62866d3SStefano Zampini   if (n_vertices) {
3939d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3940d62866d3SStefano Zampini   }
3941d62866d3SStefano Zampini   if (n_constraints) {
3942d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3943d62866d3SStefano Zampini   }
394488ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
394588ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
394688ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3947d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
394888ebb749SStefano Zampini     Mat         coarse_sub_mat;
394925084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
395088ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
395188ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
395288ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
39538bec7fa6SStefano Zampini     Mat         C_B,CPHI;
39548bec7fa6SStefano Zampini     IS          is_dummy;
39558bec7fa6SStefano Zampini     Vec         mones;
395688ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
395788ebb749SStefano Zampini     PetscReal   real_value;
395888ebb749SStefano Zampini 
3959a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3960a3df083aSStefano Zampini       Mat A;
3961a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3962a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3963a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3964a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3965a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3966a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3967a3df083aSStefano Zampini     } else {
396888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
396988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
397088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
397188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3972a3df083aSStefano Zampini     }
397388ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
397488ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3975ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
397688ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
397788ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
397888ebb749SStefano Zampini     }
397988ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
398088ebb749SStefano Zampini 
398125084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
39823301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
398325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3984ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
398588ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
398688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
398788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
398888ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
398988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
399088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
399188ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
399288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
399388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
399488ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
399588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
399688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
399788ebb749SStefano Zampini     } else {
399888ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
399988ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
400088ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
400188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
400288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
400388ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
400488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
400588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
400688ebb749SStefano Zampini     }
400788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
400888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
400988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4010511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
40114f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4012fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4013d12edf2fSStefano Zampini       PetscScalar *data,*data2;
40144f1b2e48SStefano Zampini       PetscInt    j;
4015d12edf2fSStefano Zampini 
40164f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
4017fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4018d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
401986c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4020d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4021d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
40224f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
40234f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4024d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
40254f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
40264f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
40274f1b2e48SStefano Zampini         }
4028d12edf2fSStefano Zampini       }
4029d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4030d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4031d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4032d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4033d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4034d12edf2fSStefano Zampini     }
4035d12edf2fSStefano Zampini #if 0
4036d12edf2fSStefano Zampini   {
4037d12edf2fSStefano Zampini     PetscViewer viewer;
4038d12edf2fSStefano Zampini     char filename[256];
4039ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4040d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4041d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4042ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4043ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4044ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4045d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
404672b8c272SStefano Zampini     if (save_change) {
404772b8c272SStefano Zampini       Mat phi_B;
404872b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
404972b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
405072b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
405172b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
405272b8c272SStefano Zampini     } else {
4053ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4054ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
405572b8c272SStefano Zampini     }
4056ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4057ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4058ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4059ffd830a3SStefano Zampini     }
4060ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4061ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4062ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4063ffd830a3SStefano Zampini     }
406472b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4065ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4066ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4067ffd830a3SStefano Zampini     }
4068d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4069d12edf2fSStefano Zampini   }
4070d12edf2fSStefano Zampini #endif
407181d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
40728bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
40731575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
407406656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
40758bec7fa6SStefano Zampini 
40768bec7fa6SStefano Zampini     /* check constraints */
4077a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
4078a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
40794f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
40808bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4081a00504b5SStefano Zampini     } else {
4082a00504b5SStefano Zampini       PetscScalar *data;
4083a00504b5SStefano Zampini       Mat         tmat;
4084a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4085a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4086a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4087a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4088a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4089a00504b5SStefano Zampini     }
40908bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
40918bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
40928bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
40938bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4094bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4095ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4096bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4097bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4098bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4099bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4100bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
410188ebb749SStefano Zampini     }
41028bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
41038bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
41048bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
41058bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
410625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
410788ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
410888ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
410988ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
411088ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
411188ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
411288ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
411388ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
411488ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
411588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
411688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4117ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
411888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
411988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
412088ebb749SStefano Zampini     }
412188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
412288ebb749SStefano Zampini   }
41238629588bSStefano Zampini   /* get back data */
41248629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
412588ebb749SStefano Zampini   PetscFunctionReturn(0);
412688ebb749SStefano Zampini }
412788ebb749SStefano Zampini 
412888ebb749SStefano Zampini #undef __FUNCT__
4129d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
4130d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4131aa0d41d4SStefano Zampini {
4132d65f70fdSStefano Zampini   Mat            *work_mat;
4133d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4134d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4135c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4136aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4137aa0d41d4SStefano Zampini 
4138aa0d41d4SStefano Zampini   PetscFunctionBegin;
4139d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4140d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4141d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4142d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4143aa0d41d4SStefano Zampini 
4144d65f70fdSStefano Zampini   if (!rsorted) {
4145906d46d4SStefano Zampini     const PetscInt *idxs;
4146906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4147aa0d41d4SStefano Zampini 
4148d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4149d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4150d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4151d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4152aa0d41d4SStefano Zampini     }
4153d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4154d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4155d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4156d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4157aa0d41d4SStefano Zampini     }
4158d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4159d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4160d65f70fdSStefano Zampini   } else {
4161d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4162d65f70fdSStefano Zampini     isrow_s = isrow;
4163aa0d41d4SStefano Zampini   }
4164906d46d4SStefano Zampini 
4165d65f70fdSStefano Zampini   if (!csorted) {
4166d65f70fdSStefano Zampini     if (isrow == iscol) {
4167d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4168d65f70fdSStefano Zampini       iscol_s = isrow_s;
4169d65f70fdSStefano Zampini     } else {
4170d65f70fdSStefano Zampini       const PetscInt *idxs;
4171d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4172906d46d4SStefano Zampini 
4173d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4174d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4175d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4176d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4177d65f70fdSStefano Zampini       }
4178d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4179d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4180d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4181d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4182d65f70fdSStefano Zampini       }
4183d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4184d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4185d65f70fdSStefano Zampini     }
4186d65f70fdSStefano Zampini   } else {
4187d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4188d65f70fdSStefano Zampini     iscol_s = iscol;
4189d65f70fdSStefano Zampini   }
4190d65f70fdSStefano Zampini 
4191d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4192d65f70fdSStefano Zampini 
4193d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4194906d46d4SStefano Zampini     Mat      new_mat;
4195d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4196906d46d4SStefano Zampini 
4197d65f70fdSStefano Zampini     if (!rsorted) {
4198d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4199d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4200d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4201d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4202906d46d4SStefano Zampini       }
4203d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4204d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4205d65f70fdSStefano Zampini     } else {
4206d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4207906d46d4SStefano Zampini     }
4208d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4209d65f70fdSStefano Zampini 
4210d65f70fdSStefano Zampini     if (!csorted) {
4211d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4212d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4213d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4214d65f70fdSStefano Zampini       } else {
4215d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4216f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4217d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4218d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4219d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4220d65f70fdSStefano Zampini         }
4221d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4222d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4223d65f70fdSStefano Zampini       }
4224d65f70fdSStefano Zampini     } else {
4225d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4226d65f70fdSStefano Zampini     }
4227d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4228d65f70fdSStefano Zampini 
4229d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4230d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4231d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4232d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4233d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4234d65f70fdSStefano Zampini   }
4235d65f70fdSStefano Zampini 
4236d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4237d65f70fdSStefano Zampini   *B = work_mat[0];
4238d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4239d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4240d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4241d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4242d65f70fdSStefano Zampini }
4243d65f70fdSStefano Zampini 
4244d65f70fdSStefano Zampini #undef __FUNCT__
42455e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
42465e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4247aa0d41d4SStefano Zampini {
4248aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
42495e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4250d65f70fdSStefano Zampini   Mat            new_mat;
42515e8657edSStefano Zampini   IS             is_local,is_global;
4252d65f70fdSStefano Zampini   PetscInt       local_size;
4253d65f70fdSStefano Zampini   PetscBool      isseqaij;
4254aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4255aa0d41d4SStefano Zampini 
4256aa0d41d4SStefano Zampini   PetscFunctionBegin;
4257aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
42585e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
42595e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4260b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4261aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
4262d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4263aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4264906d46d4SStefano Zampini 
4265906d46d4SStefano Zampini   /* check */
4266906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4267906d46d4SStefano Zampini     Vec       x,x_change;
4268906d46d4SStefano Zampini     PetscReal error;
4269906d46d4SStefano Zampini 
42705e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4271906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
42725e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4273e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4274e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4275d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
427688428137SStefano Zampini     if (!pcbddc->change_interior) {
427788428137SStefano Zampini       const PetscScalar *x,*y,*v;
427888428137SStefano Zampini       PetscReal         lerror = 0.;
427988428137SStefano Zampini       PetscInt          i;
428088428137SStefano Zampini 
428188428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
428288428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
428388428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
428488428137SStefano Zampini       for (i=0;i<local_size;i++)
428588428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
428688428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
428788428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
428888428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
428988428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
429088428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
429188428137SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on I: %1.6e\n",error);CHKERRQ(ierr);
429288428137SStefano Zampini     }
4293e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4294e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4295906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4296906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4297906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4298906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
4299906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4300906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4301906d46d4SStefano Zampini   }
4302906d46d4SStefano Zampini 
430322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
43049b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
430522d5777bSStefano Zampini   if (isseqaij) {
4306a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4307a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4308aa0d41d4SStefano Zampini   } else {
4309a00504b5SStefano Zampini     Mat work_mat;
43101cf9b237SStefano Zampini 
4311a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4312aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4313a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
43141d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4315aa0d41d4SStefano Zampini   }
43163301b35fSStefano Zampini   if (matis->A->symmetric_set) {
43173301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4318e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
43193301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4320e496cd5dSStefano Zampini #endif
43213301b35fSStefano Zampini   }
4322d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4323aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4324aa0d41d4SStefano Zampini }
4325aa0d41d4SStefano Zampini 
4326aa0d41d4SStefano Zampini #undef __FUNCT__
4327a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
43288ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4329a64d13efSStefano Zampini {
4330a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4331a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4332d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
433353892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
43343a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
43353a50541eSStefano Zampini   PetscInt        vbs,bs;
43366816873aSStefano Zampini   PetscBT         bitmask=NULL;
4337a64d13efSStefano Zampini   PetscErrorCode  ierr;
4338a64d13efSStefano Zampini 
4339a64d13efSStefano Zampini   PetscFunctionBegin;
4340b23d619eSStefano Zampini   /*
4341b23d619eSStefano Zampini     No need to setup local scatters if
4342b23d619eSStefano Zampini       - primal space is unchanged
4343b23d619eSStefano Zampini         AND
4344b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4345b23d619eSStefano Zampini         AND
4346b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4347b23d619eSStefano Zampini   */
4348b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4349f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4350f4ddd8eeSStefano Zampini   }
4351f4ddd8eeSStefano Zampini   /* destroy old objects */
4352f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4353f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4354f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4355a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4356b371cd4fSStefano Zampini   n_B = pcis->n_B;
4357b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4358b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
43593a50541eSStefano Zampini 
4360a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
43616816873aSStefano Zampini 
436253892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4363b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4364854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4365a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4366a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
43670e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4368a64d13efSStefano Zampini     }
4369a64d13efSStefano Zampini 
4370a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
43714641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
43726816873aSStefano Zampini         idx_R_local[n_R++] = i;
4373a64d13efSStefano Zampini       }
4374a64d13efSStefano Zampini     }
4375df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4376df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
43776816873aSStefano Zampini 
4378df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4379df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
43806816873aSStefano Zampini   }
43813a50541eSStefano Zampini 
43823a50541eSStefano Zampini   /* Block code */
43833a50541eSStefano Zampini   vbs = 1;
43843a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
43853a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
43863a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
43873a50541eSStefano Zampini     PetscInt  *vary;
4388b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4389785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
43903a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4391d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4392d3df7717SStefano 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 */
43930e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4394d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
43953a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
43963a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
43973a50541eSStefano Zampini           break;
43983a50541eSStefano Zampini         }
43993a50541eSStefano Zampini       }
4400d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4401d3df7717SStefano Zampini     } else {
4402d3df7717SStefano Zampini       /* Verify directly the R set */
4403d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4404d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4405d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4406d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4407d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4408d3df7717SStefano Zampini             break;
4409d3df7717SStefano Zampini           }
4410d3df7717SStefano Zampini         }
4411d3df7717SStefano Zampini       }
4412d3df7717SStefano Zampini     }
44133a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
44143a50541eSStefano Zampini       vbs = bs;
44153a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
44163a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
44173a50541eSStefano Zampini       }
44183a50541eSStefano Zampini     }
44193a50541eSStefano Zampini   }
44203a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4421b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4422df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
442353892102SStefano Zampini 
4424df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4425df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
442653892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4427df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
442853892102SStefano Zampini   } else {
44293a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
443053892102SStefano Zampini   }
4431a64d13efSStefano Zampini 
4432a64d13efSStefano Zampini   /* print some info if requested */
4433a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4434a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4435a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
44361575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4437a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4438a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
44394f1b2e48SStefano 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);
4440a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4441a64d13efSStefano Zampini   }
4442a64d13efSStefano Zampini 
4443a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4444b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
44456816873aSStefano Zampini     IS       is_aux1,is_aux2;
44466816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
44476816873aSStefano Zampini 
44483a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4449854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4450854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4451a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
44524641a718SStefano Zampini     for (i=0; i<n_D; i++) {
44534641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
44544641a718SStefano Zampini     }
4455a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4456a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
44574641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
44584641a718SStefano Zampini         aux_array1[j++] = i;
4459a64d13efSStefano Zampini       }
4460a64d13efSStefano Zampini     }
4461a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4462a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4463a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
44644641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
44654641a718SStefano Zampini         aux_array2[j++] = i;
4466a64d13efSStefano Zampini       }
4467a64d13efSStefano Zampini     }
4468a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4469a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4470a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4471a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4472a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4473a64d13efSStefano Zampini 
44748eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4475785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4476a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
44774641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
44784641a718SStefano Zampini           aux_array1[j++] = i;
4479a64d13efSStefano Zampini         }
4480a64d13efSStefano Zampini       }
4481a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4482a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4483a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4484a64d13efSStefano Zampini     }
44854641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
44863a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4487d62866d3SStefano Zampini   } else {
4488df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
44896816873aSStefano Zampini     IS                 tis;
44906816873aSStefano Zampini     PetscInt           schur_size;
44916816873aSStefano Zampini 
4492df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
44936816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4494df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
44956816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
44966816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
44976816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
44986816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
44996816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4500d62866d3SStefano Zampini     }
4501d62866d3SStefano Zampini   }
4502a64d13efSStefano Zampini   PetscFunctionReturn(0);
4503a64d13efSStefano Zampini }
4504a64d13efSStefano Zampini 
4505304d26faSStefano Zampini 
4506304d26faSStefano Zampini #undef __FUNCT__
4507304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4508684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4509304d26faSStefano Zampini {
4510304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4511304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4512304d26faSStefano Zampini   PC             pc_temp;
4513304d26faSStefano Zampini   Mat            A_RR;
4514f4ddd8eeSStefano Zampini   MatReuse       reuse;
4515304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4516304d26faSStefano Zampini   PetscReal      value;
451704708bb6SStefano Zampini   PetscInt       n_D,n_R;
4518c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4519304d26faSStefano Zampini   PetscErrorCode ierr;
4520e604994aSStefano Zampini   /* prefixes stuff */
4521312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4522e604994aSStefano Zampini   size_t         len;
4523304d26faSStefano Zampini 
4524304d26faSStefano Zampini   PetscFunctionBegin;
4525304d26faSStefano Zampini 
4526e604994aSStefano Zampini   /* compute prefixes */
4527e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4528e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4529e604994aSStefano Zampini   if (!pcbddc->current_level) {
4530e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4531e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4532e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4533e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4534e604994aSStefano Zampini   } else {
4535e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4536312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4537e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4538e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4539312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4540312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
454134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
454234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4543e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4544e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4545e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4546e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4547e604994aSStefano Zampini   }
4548e604994aSStefano Zampini 
4549304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4550684f6988SStefano Zampini   if (dirichlet) {
4551d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4552450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
45539a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4554450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4555a3df083aSStefano Zampini         Mat    A_IIn;
4556a3df083aSStefano Zampini 
4557a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4558a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4559a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4560a3df083aSStefano Zampini       }
4561450f8f5eSStefano Zampini     }
45623301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
45633301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4564964fefecSStefano Zampini     }
4565ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4566964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4567304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4568304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4569304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4570304d26faSStefano Zampini       /* default */
4571304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4572e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
45739577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4574304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
45759577ea80SStefano Zampini       if (issbaij) {
45769577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
45779577ea80SStefano Zampini       } else {
4578304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
45799577ea80SStefano Zampini       }
4580304d26faSStefano Zampini       /* Allow user's customization */
4581304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4582304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4583304d26faSStefano Zampini     }
4584d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4585b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4586df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4587d62866d3SStefano Zampini 
4588df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4589d5574798SStefano Zampini     }
4590304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4591304d26faSStefano Zampini     if (!n_D) {
4592304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4593304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4594304d26faSStefano Zampini     }
4595304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4596304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4597304d26faSStefano Zampini     /* set ksp_D into pcis data */
4598304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4599304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4600304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4601684f6988SStefano Zampini   }
4602304d26faSStefano Zampini 
4603304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4604684f6988SStefano Zampini   A_RR = 0;
4605684f6988SStefano Zampini   if (neumann) {
4606d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
460704708bb6SStefano Zampini     PetscInt        ibs,mbs;
460804708bb6SStefano Zampini     PetscBool       issbaij;
460904708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4610f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
46118ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4612f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4613f4ddd8eeSStefano Zampini       PetscInt nn_R;
461481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4615f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4616f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4617f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4618f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4619f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4620f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4621f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4622727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4623f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4624f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4625f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4626f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4627f4ddd8eeSStefano Zampini         }
4628f4ddd8eeSStefano Zampini       }
4629f4ddd8eeSStefano Zampini       /* last check */
4630d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4631f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4632f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4633f4ddd8eeSStefano Zampini       }
4634f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4635f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4636f4ddd8eeSStefano Zampini     }
4637a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4638af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4639af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
464004708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
464104708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
464204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
464304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
464404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4645af732b37SStefano Zampini       } else {
4646511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
46476816873aSStefano Zampini       }
464804708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
464904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
465004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
465104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
465204708bb6SStefano Zampini       } else {
4653511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
465404708bb6SStefano Zampini       }
465504708bb6SStefano Zampini     }
4656a00504b5SStefano Zampini     /* extract A_RR */
4657b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4658a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4659a00504b5SStefano Zampini 
4660a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
466116e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4662a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
466316e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
466416e386b8SStefano Zampini         } else {
4665a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4666a00504b5SStefano Zampini         }
4667a00504b5SStefano Zampini       } else {
4668a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4669a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4670a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4671a00504b5SStefano Zampini       }
4672a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4673f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
467416e386b8SStefano Zampini     }
46753301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
46763301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
46776816873aSStefano Zampini     }
4678f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4679304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4680304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4681304d26faSStefano Zampini       /* default */
4682304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4683e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4684304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
46859577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
46869577ea80SStefano Zampini       if (issbaij) {
46879577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
46889577ea80SStefano Zampini       } else {
4689304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
46909577ea80SStefano Zampini       }
4691304d26faSStefano Zampini       /* Allow user's customization */
4692304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4693304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4694304d26faSStefano Zampini     }
4695304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4696304d26faSStefano Zampini     if (!n_R) {
4697304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4698304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4699304d26faSStefano Zampini     }
47005cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4701df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4702b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4703df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4704d62866d3SStefano Zampini 
4705df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4706d62866d3SStefano Zampini     }
4707304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4708304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4709684f6988SStefano Zampini   }
4710304d26faSStefano Zampini 
4711684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4712684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
47131575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4714684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4715684f6988SStefano Zampini   }
4716c7017625SStefano Zampini 
4717c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4718c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4719c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4720c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4721c7017625SStefano Zampini   }
4722c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4723c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4724c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4725c7017625SStefano Zampini   }
4726c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4727c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4728c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4729c7017625SStefano Zampini   }
4730c7017625SStefano Zampini 
4731c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4732c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4733684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
47340fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
47350fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
47360fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
47370fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
47380fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4739e604994aSStefano 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);
4740c7017625SStefano Zampini       if (check_corr[0]) {
4741c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4742c7017625SStefano Zampini       }
4743304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4744304d26faSStefano Zampini     }
4745684f6988SStefano Zampini     if (neumann) { /* Neumann */
47460fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
47470fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
47480fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
47490fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
47500fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4751e604994aSStefano 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);
4752c7017625SStefano Zampini       if (check_corr[1]) {
4753c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4754c7017625SStefano Zampini       }
4755304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4756304d26faSStefano Zampini     }
4757684f6988SStefano Zampini   }
47585cbda25cSStefano Zampini   /* free Neumann problem's matrix */
47595cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4760304d26faSStefano Zampini   PetscFunctionReturn(0);
4761304d26faSStefano Zampini }
4762304d26faSStefano Zampini 
4763304d26faSStefano Zampini #undef __FUNCT__
4764ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
476580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4766674ae819SStefano Zampini {
4767674ae819SStefano Zampini   PetscErrorCode  ierr;
4768674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4769be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4770b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4771674ae819SStefano Zampini 
4772674ae819SStefano Zampini   PetscFunctionBegin;
4773b334f244SStefano Zampini   if (!reuse_solver) {
477480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
477520c7b377SStefano Zampini   }
477680677318SStefano Zampini   if (!pcbddc->switch_static) {
477780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
477880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
477980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
478020c7b377SStefano Zampini     }
4781b334f244SStefano Zampini     if (!reuse_solver) {
478280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
478380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
478420c7b377SStefano Zampini     } else {
4785df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4786be83ff47SStefano Zampini 
4787df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4788df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
478920c7b377SStefano Zampini     }
4790be83ff47SStefano Zampini   } else {
479180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
479680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
479780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
479880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4800674ae819SStefano Zampini     }
4801674ae819SStefano Zampini   }
4802b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
480380677318SStefano Zampini     if (applytranspose) {
480480677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
480580677318SStefano Zampini     } else {
480680677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
480780677318SStefano Zampini     }
4808be83ff47SStefano Zampini   } else {
4809df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4810be83ff47SStefano Zampini 
4811be83ff47SStefano Zampini     if (applytranspose) {
4812df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4813be83ff47SStefano Zampini     } else {
4814df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4815be83ff47SStefano Zampini     }
4816be83ff47SStefano Zampini   }
481780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
481880677318SStefano Zampini   if (!pcbddc->switch_static) {
4819b334f244SStefano Zampini     if (!reuse_solver) {
482080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
482180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4822be83ff47SStefano Zampini     } else {
4823df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4824be83ff47SStefano Zampini 
4825df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4826df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4827be83ff47SStefano Zampini     }
482880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
482980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
483080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
483180677318SStefano Zampini     }
483280677318SStefano Zampini   } else {
483380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
483880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
483980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
484080677318SStefano Zampini     }
484180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
484280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
484380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
484480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4845674ae819SStefano Zampini   }
4846674ae819SStefano Zampini   PetscFunctionReturn(0);
4847674ae819SStefano Zampini }
4848674ae819SStefano Zampini 
4849dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4850674ae819SStefano Zampini #undef __FUNCT__
4851674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4852dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4853674ae819SStefano Zampini {
4854674ae819SStefano Zampini   PetscErrorCode ierr;
4855674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4856674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4857674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4858674ae819SStefano Zampini 
4859674ae819SStefano Zampini   PetscFunctionBegin;
4860dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
48614fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4862dc359a40SStefano Zampini     if (applytranspose) {
4863674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
48648eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4865dc359a40SStefano Zampini     } else {
4866674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4867674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
486815aaf578SStefano Zampini     }
48694fee134fSStefano Zampini   } else {
48704fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
48714fee134fSStefano Zampini   }
4872efc2fbd9SStefano Zampini 
4873efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
48744f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4875efc2fbd9SStefano Zampini     PetscScalar *array;
48764f1b2e48SStefano Zampini     PetscInt    j;
4877efc2fbd9SStefano Zampini 
4878efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
48794f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4880efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4881efc2fbd9SStefano Zampini   }
4882efc2fbd9SStefano Zampini 
488312edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
488412edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
488512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
488612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
488712edc857SStefano Zampini 
48889f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
488912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
489051694757SStefano Zampini     Mat          coarse_mat;
4891964fefecSStefano Zampini     Vec          rhs,sol;
489251694757SStefano Zampini     MatNullSpace nullsp;
489327b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4894964fefecSStefano Zampini 
489527b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
489627b6a85dSStefano Zampini       PC        coarse_pc;
489727b6a85dSStefano Zampini 
489827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
489927b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
490027b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
490127b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
490227b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
490327b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
49043bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
490527b6a85dSStefano Zampini       }
490627b6a85dSStefano Zampini     }
4907964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4908964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
490951694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
491051694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
491151694757SStefano Zampini     if (nullsp) {
491251694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
491351694757SStefano Zampini     }
491412edc857SStefano Zampini     if (applytranspose) {
49159a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4916964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
49172701bc32SStefano Zampini     } else {
49181f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
49192701bc32SStefano Zampini         PC        coarse_pc;
49202701bc32SStefano Zampini 
49212701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
49222701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
49233e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
49242701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
492512edc857SStefano Zampini       } else {
4926964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
492712edc857SStefano Zampini       }
49282701bc32SStefano Zampini     }
49291d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
493027b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
493127b6a85dSStefano Zampini       PC        coarse_pc;
493227b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
493327b6a85dSStefano Zampini 
493427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
493527b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
493627b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
49373bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
493827b6a85dSStefano Zampini     }
493951694757SStefano Zampini     if (nullsp) {
494051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
494151694757SStefano Zampini     }
494212edc857SStefano Zampini   }
4943674ae819SStefano Zampini 
4944674ae819SStefano Zampini   /* Local solution on R nodes */
49454fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
494680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
49479f00e9b4SStefano Zampini   }
49489f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
49499f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
495012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4951674ae819SStefano Zampini 
49524fee134fSStefano Zampini   /* Sum contributions from the two levels */
49534fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4954dc359a40SStefano Zampini     if (applytranspose) {
4955dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4956dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4957dc359a40SStefano Zampini     } else {
4958674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
49598eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4960dc359a40SStefano Zampini     }
4961efc2fbd9SStefano Zampini     /* store p0 */
49624f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4963efc2fbd9SStefano Zampini       PetscScalar *array;
49644f1b2e48SStefano Zampini       PetscInt    j;
4965efc2fbd9SStefano Zampini 
4966efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
49674f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4968efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4969efc2fbd9SStefano Zampini     }
49704fee134fSStefano Zampini   } else { /* expand the coarse solution */
49714fee134fSStefano Zampini     if (applytranspose) {
49724fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
49734fee134fSStefano Zampini     } else {
49744fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
49754fee134fSStefano Zampini     }
49764fee134fSStefano Zampini   }
4977674ae819SStefano Zampini   PetscFunctionReturn(0);
4978674ae819SStefano Zampini }
4979674ae819SStefano Zampini 
4980674ae819SStefano Zampini #undef __FUNCT__
4981674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
498212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4983674ae819SStefano Zampini {
4984674ae819SStefano Zampini   PetscErrorCode ierr;
4985674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
498658da7f69SStefano Zampini   PetscScalar    *array;
498712edc857SStefano Zampini   Vec            from,to;
4988674ae819SStefano Zampini 
4989674ae819SStefano Zampini   PetscFunctionBegin;
499012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
499112edc857SStefano Zampini     from = pcbddc->coarse_vec;
499212edc857SStefano Zampini     to = pcbddc->vec1_P;
499312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
499412edc857SStefano Zampini       Vec tvec;
499558da7f69SStefano Zampini 
499658da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
499758da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
499812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
499958da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
500058da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
500158da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
500212edc857SStefano Zampini     }
500312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
500412edc857SStefano Zampini     from = pcbddc->vec1_P;
500512edc857SStefano Zampini     to = pcbddc->coarse_vec;
500612edc857SStefano Zampini   }
500712edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5008674ae819SStefano Zampini   PetscFunctionReturn(0);
5009674ae819SStefano Zampini }
5010674ae819SStefano Zampini 
5011674ae819SStefano Zampini #undef __FUNCT__
5012674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
501312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5014674ae819SStefano Zampini {
5015674ae819SStefano Zampini   PetscErrorCode ierr;
5016674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
501758da7f69SStefano Zampini   PetscScalar    *array;
501812edc857SStefano Zampini   Vec            from,to;
5019674ae819SStefano Zampini 
5020674ae819SStefano Zampini   PetscFunctionBegin;
502112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
502212edc857SStefano Zampini     from = pcbddc->coarse_vec;
502312edc857SStefano Zampini     to = pcbddc->vec1_P;
502412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
502512edc857SStefano Zampini     from = pcbddc->vec1_P;
502612edc857SStefano Zampini     to = pcbddc->coarse_vec;
502712edc857SStefano Zampini   }
502812edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
502912edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
503012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
503112edc857SStefano Zampini       Vec tvec;
503258da7f69SStefano Zampini 
503312edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
503458da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
503558da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
503658da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
503758da7f69SStefano Zampini     }
503858da7f69SStefano Zampini   } else {
503958da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
504058da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
504112edc857SStefano Zampini     }
504212edc857SStefano Zampini   }
5043674ae819SStefano Zampini   PetscFunctionReturn(0);
5044674ae819SStefano Zampini }
5045674ae819SStefano Zampini 
5046984c4197SStefano Zampini /* uncomment for testing purposes */
5047984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5048674ae819SStefano Zampini #undef __FUNCT__
5049674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
5050674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5051674ae819SStefano Zampini {
5052674ae819SStefano Zampini   PetscErrorCode    ierr;
5053674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5054674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5055674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5056984c4197SStefano Zampini   /* one and zero */
5057984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5058984c4197SStefano Zampini   /* space to store constraints and their local indices */
50599162d606SStefano Zampini   PetscScalar       *constraints_data;
50609162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
50619162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
50629162d606SStefano Zampini   PetscInt          *constraints_n;
5063984c4197SStefano Zampini   /* iterators */
5064b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5065984c4197SStefano Zampini   /* BLAS integers */
5066e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5067e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5068c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5069727cdba6SStefano Zampini   /* reuse */
50700e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
50710e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5072984c4197SStefano Zampini   /* change of basis */
5073b3d85658SStefano Zampini   PetscBool         qr_needed;
50749162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5075984c4197SStefano Zampini   /* auxiliary stuff */
507664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
50778a0068c3SStefano Zampini   PetscInt          ncc;
5078984c4197SStefano Zampini   /* some quantities */
507945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5080a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
5081984c4197SStefano Zampini 
5082674ae819SStefano Zampini   PetscFunctionBegin;
50838e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
50848e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
50858e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
508616909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5087088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5088088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
50890e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
50900e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
50910e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
50920e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
50930e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5094088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5095cf5a6209SStefano Zampini 
5096cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
50979162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5098cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5099cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5100cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5101cf5a6209SStefano Zampini     PetscScalar  *array;
5102cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5103cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5104674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5105b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5106674ae819SStefano Zampini     PetscScalar  *work;
5107674ae819SStefano Zampini     PetscReal    *singular_vals;
5108674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5109674ae819SStefano Zampini     PetscReal    *rwork;
5110674ae819SStefano Zampini #endif
5111674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5112674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5113674ae819SStefano Zampini #else
5114964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5115964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5116674ae819SStefano Zampini #endif
5117674ae819SStefano Zampini 
5118674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5119d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5120e4d548c7SStefano Zampini     /* print some info */
51215c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5122e4d548c7SStefano Zampini       PetscInt nv;
5123e4d548c7SStefano Zampini 
5124c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5125e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5126e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5127e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5128e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5129e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5130e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5131e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5132e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5133e4d548c7SStefano Zampini     }
5134e4d548c7SStefano Zampini 
5135d06fc5fdSStefano Zampini     /* free unneeded index sets */
5136d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5137d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5138674ae819SStefano Zampini     }
5139d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5140d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5141d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5142d06fc5fdSStefano Zampini       }
5143d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5144d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5145d06fc5fdSStefano Zampini     }
5146d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5147d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5148d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5149d06fc5fdSStefano Zampini       }
5150d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5151d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5152d06fc5fdSStefano Zampini     }
515370022509SStefano Zampini 
5154674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5155674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5156674ae819SStefano Zampini     if (nearnullsp) {
5157674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5158f4ddd8eeSStefano Zampini       /* remove any stored info */
5159f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5160f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5161f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5162f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5163f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5164473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5165f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5166f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5167f4ddd8eeSStefano Zampini       }
5168984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5169984c4197SStefano Zampini       nnsp_size = 0;
5170674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5171674ae819SStefano Zampini     }
5172984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5173984c4197SStefano Zampini     max_constraints = nnsp_size;
5174984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5175984c4197SStefano Zampini 
5176674ae819SStefano Zampini     /*
5177674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
51789162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
51799162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
51809162d606SStefano Zampini          There can be multiple constraints per connected component
5181674ae819SStefano Zampini                                                                                                                                                            */
5182674ae819SStefano Zampini     n_vertices = 0;
5183674ae819SStefano Zampini     if (ISForVertices) {
5184674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5185674ae819SStefano Zampini     }
51869162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
51879162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
51889162d606SStefano Zampini 
51899162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
51909162d606SStefano Zampini     total_counts *= max_constraints;
5191674ae819SStefano Zampini     total_counts += n_vertices;
51924641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
51939162d606SStefano Zampini 
5194674ae819SStefano Zampini     total_counts = 0;
5195674ae819SStefano Zampini     max_size_of_constraint = 0;
5196674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
51979162d606SStefano Zampini       IS used_is;
5198674ae819SStefano Zampini       if (i<n_ISForEdges) {
51999162d606SStefano Zampini         used_is = ISForEdges[i];
5200674ae819SStefano Zampini       } else {
52019162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5202674ae819SStefano Zampini       }
52039162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5204674ae819SStefano Zampini       total_counts += j;
5205674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5206674ae819SStefano Zampini     }
52079162d606SStefano 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);
52089162d606SStefano Zampini 
5209984c4197SStefano Zampini     /* get local part of global near null space vectors */
5210785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5211984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5212984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5213e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5214e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5215984c4197SStefano Zampini     }
5216674ae819SStefano Zampini 
5217242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5218242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5219a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5220242a89d7SStefano Zampini 
5221984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5222a773dcb8SStefano Zampini     if (!skip_lapack) {
5223674ae819SStefano Zampini       PetscScalar temp_work;
5224911cabfeSStefano Zampini 
5225674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5226984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5227785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5228785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5229785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5230674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5231785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5232674ae819SStefano Zampini #endif
5233674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5234c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5235c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5236674ae819SStefano Zampini       lwork = -1;
5237674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5238674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5239c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5240674ae819SStefano Zampini #else
5241c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5242674ae819SStefano Zampini #endif
5243674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5244984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5245674ae819SStefano Zampini #else /* on missing GESVD */
5246674ae819SStefano Zampini       /* SVD */
5247674ae819SStefano Zampini       PetscInt max_n,min_n;
5248674ae819SStefano Zampini       max_n = max_size_of_constraint;
5249984c4197SStefano Zampini       min_n = max_constraints;
5250984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5251674ae819SStefano Zampini         min_n = max_size_of_constraint;
5252984c4197SStefano Zampini         max_n = max_constraints;
5253674ae819SStefano Zampini       }
5254785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5255674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5256785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5257674ae819SStefano Zampini #endif
5258674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5259674ae819SStefano Zampini       lwork = -1;
5260e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5261e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5262b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5263674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5264674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
52659162d606SStefano 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));
5266674ae819SStefano Zampini #else
52679162d606SStefano 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));
5268674ae819SStefano Zampini #endif
5269674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5270984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5271984c4197SStefano Zampini #endif /* on missing GESVD */
5272674ae819SStefano Zampini       /* Allocate optimal workspace */
5273674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5274854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5275674ae819SStefano Zampini     }
5276674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5277674ae819SStefano Zampini     total_counts = 0;
52789162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
52799162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5280674ae819SStefano Zampini     /* vertices */
52819162d606SStefano Zampini     if (n_vertices) {
5282674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
52839162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5284674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
52859162d606SStefano Zampini         constraints_n[total_counts] = 1;
52869162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
52879162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
52889162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5289674ae819SStefano Zampini         total_counts++;
5290674ae819SStefano Zampini       }
5291674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5292674ae819SStefano Zampini       n_vertices = total_counts;
5293674ae819SStefano Zampini     }
5294984c4197SStefano Zampini 
5295674ae819SStefano Zampini     /* edges and faces */
52969162d606SStefano Zampini     total_counts_cc = total_counts;
5297911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
52989162d606SStefano Zampini       IS        used_is;
52999162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
53009162d606SStefano Zampini 
5301911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
53029162d606SStefano Zampini         used_is = ISForEdges[ncc];
5303984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5304674ae819SStefano Zampini       } else {
53059162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5306984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5307674ae819SStefano Zampini       }
5308674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
53099162d606SStefano Zampini 
53109162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
53119162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5312984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5313984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5314674ae819SStefano Zampini       if (nnsp_has_cnst) {
53155b08dc53SStefano Zampini         PetscScalar quad_value;
53169162d606SStefano Zampini 
53179162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
53189162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
53199162d606SStefano Zampini 
5320a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5321674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5322a773dcb8SStefano Zampini         } else {
5323a773dcb8SStefano Zampini           quad_value = 1.0;
5324a773dcb8SStefano Zampini         }
5325674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
53269162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5327674ae819SStefano Zampini         }
53289162d606SStefano Zampini         temp_constraints++;
5329674ae819SStefano Zampini         total_counts++;
5330674ae819SStefano Zampini       }
5331674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5332984c4197SStefano Zampini         PetscReal real_value;
53339162d606SStefano Zampini         PetscScalar *ptr_to_data;
53349162d606SStefano Zampini 
5335984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
53369162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5337674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
53389162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5339674ae819SStefano Zampini         }
5340984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5341984c4197SStefano Zampini         /* check if array is null on the connected component */
5342e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
53439162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
53445b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5345674ae819SStefano Zampini           temp_constraints++;
5346674ae819SStefano Zampini           total_counts++;
53479162d606SStefano Zampini           if (!idxs_copied) {
53489162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
53499162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5350674ae819SStefano Zampini           }
5351674ae819SStefano Zampini         }
53529162d606SStefano Zampini       }
53539162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
535445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5355eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5356a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
53579162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
53589162d606SStefano Zampini 
53599162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5360a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
53619162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5362a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
53639162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5364a773dcb8SStefano Zampini         } else { /* perform SVD */
5365984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
53669162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5367674ae819SStefano Zampini 
5368674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5369984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5370984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5371984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5372984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5373984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5374984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5375984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5376984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5377674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5378e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5379984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5380674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5381674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
53829162d606SStefano 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));
5383674ae819SStefano Zampini             }
5384674ae819SStefano Zampini           }
5385e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5386e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5387e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5388674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5389c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5390674ae819SStefano Zampini #else
5391c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5392674ae819SStefano Zampini #endif
5393674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5394984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5395984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5396674ae819SStefano Zampini           j = 0;
5397984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5398674ae819SStefano Zampini           total_counts = total_counts-j;
539945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5400e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5401c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5402c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5403c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5404c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5405c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5406c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5407674ae819SStefano Zampini           if (j<temp_constraints) {
5408984c4197SStefano Zampini             PetscInt ii;
5409984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5410674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54119162d606SStefano 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));
5412674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5413984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5414674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
54159162d606SStefano 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];
5416674ae819SStefano Zampini               }
5417674ae819SStefano Zampini             }
5418674ae819SStefano Zampini           }
5419674ae819SStefano Zampini #else  /* on missing GESVD */
5420e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5421e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5422b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5423674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5424674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
54259162d606SStefano 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));
5426674ae819SStefano Zampini #else
54279162d606SStefano 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));
5428674ae819SStefano Zampini #endif
5429984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5430674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5431984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5432e310c8b4SStefano Zampini           k = temp_constraints;
5433e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5434674ae819SStefano Zampini           j = 0;
5435e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
543645a1bb75SStefano Zampini           valid_constraints = k-j;
5437911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5438984c4197SStefano Zampini #endif /* on missing GESVD */
5439674ae819SStefano Zampini         }
5440a773dcb8SStefano Zampini       }
54419162d606SStefano Zampini       /* update pointers information */
54429162d606SStefano Zampini       if (valid_constraints) {
54439162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
54449162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
54459162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
54469162d606SStefano Zampini         /* set change_of_basis flag */
544745a1bb75SStefano Zampini         if (boolforchange) {
5448b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
54499162d606SStefano Zampini         }
5450b3d85658SStefano Zampini         total_counts_cc++;
545145a1bb75SStefano Zampini       }
545245a1bb75SStefano Zampini     }
5453984c4197SStefano Zampini     /* free workspace */
54548f1c130eSStefano Zampini     if (!skip_lapack) {
5455984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5456984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5457984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5458984c4197SStefano Zampini #endif
5459984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5460984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5461984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5462984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5463984c4197SStefano Zampini #endif
5464984c4197SStefano Zampini     }
5465984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5466984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5467984c4197SStefano Zampini     }
5468984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5469cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5470cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5471cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5472cf5a6209SStefano Zampini     }
5473cf5a6209SStefano Zampini     if (n_ISForFaces) {
5474cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5475cf5a6209SStefano Zampini     }
5476cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5477cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5478cf5a6209SStefano Zampini     }
5479cf5a6209SStefano Zampini     if (n_ISForEdges) {
5480cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5481cf5a6209SStefano Zampini     }
5482cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
548308122e43SStefano Zampini   } else {
548408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5485984c4197SStefano Zampini 
548608122e43SStefano Zampini     total_counts = 0;
548708122e43SStefano Zampini     n_vertices = 0;
5488d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5489d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
549008122e43SStefano Zampini     }
549108122e43SStefano Zampini     max_constraints = 0;
54929162d606SStefano Zampini     total_counts_cc = 0;
549308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
549408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
54959162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
549608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
549708122e43SStefano Zampini     }
54989162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
54999162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
55009162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
55019162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
550274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
55039162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
55049162d606SStefano Zampini     total_counts_cc = 0;
55059162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
55069162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
55079162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
550808122e43SStefano Zampini       }
550908122e43SStefano Zampini     }
55109162d606SStefano Zampini #if 0
55119162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
55129162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
55139162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
55149162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
55159162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
55169162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
55179162d606SStefano Zampini       }
55189162d606SStefano Zampini       printf("\n");
55199162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
55209162d606SStefano Zampini     }
55211b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
55228bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
55231b968477SStefano Zampini     }
55241b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
55258bec7fa6SStefano 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]);
55261b968477SStefano Zampini     }
552708122e43SStefano Zampini #endif
552808122e43SStefano Zampini 
55298bec7fa6SStefano Zampini     max_size_of_constraint = 0;
55309162d606SStefano 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]);
55319162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
553208122e43SStefano Zampini     /* Change of basis */
5533b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
553408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
553508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
553608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5537b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
553808122e43SStefano Zampini         }
553908122e43SStefano Zampini       }
554008122e43SStefano Zampini     }
554108122e43SStefano Zampini   }
5542984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
55434f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
554408122e43SStefano Zampini 
55459162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
55469162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
5547*eee23b56SStefano 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);
5548674ae819SStefano Zampini 
5549674ae819SStefano Zampini   /* Create constraint matrix */
5550674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
555116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5552984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5553984c4197SStefano Zampini 
5554984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5555a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5556a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
555774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5558984c4197SStefano Zampini   total_primal_vertices=0;
5559b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
55609162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
55619162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
556272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
55639162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5564b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
556564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
55669162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
55679162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5568a717540cSStefano Zampini       }
5569b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
557091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5571a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5572a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5573a717540cSStefano Zampini       }
5574fa434743SStefano Zampini     } else {
5575b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5576fa434743SStefano Zampini     }
5577a717540cSStefano Zampini   }
5578b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5579b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5580674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
558170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
55824f1b2e48SStefano 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);
55830e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
55840e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5585984c4197SStefano Zampini 
5586984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
558774d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5588785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5589984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
559074d5cdf7SStefano Zampini 
5591984c4197SStefano Zampini   j = total_primal_vertices;
559274d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5593b3d85658SStefano Zampini   cum = total_primal_vertices;
55949162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
55954641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5596b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5597b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5598b3d85658SStefano Zampini       cum++;
55999162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
560074d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
560174d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
560274d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
560374d5cdf7SStefano Zampini       }
56049162d606SStefano Zampini       j += constraints_n[i];
5605674ae819SStefano Zampini     }
5606674ae819SStefano Zampini   }
5607674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5608674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5609088faed8SStefano Zampini 
5610674ae819SStefano Zampini   /* set values in constraint matrix */
5611984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
56120e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5613674ae819SStefano Zampini   }
5614984c4197SStefano Zampini   total_counts = total_primal_vertices;
56159162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
56164641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
56179162d606SStefano Zampini       PetscInt *cols;
56189162d606SStefano Zampini 
56199162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
56209162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
56219162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
56229162d606SStefano Zampini         PetscInt    row = total_counts+k;
56239162d606SStefano Zampini         PetscScalar *vals;
56249162d606SStefano Zampini 
56259162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
56269162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
56279162d606SStefano Zampini       }
56289162d606SStefano Zampini       total_counts += constraints_n[i];
5629674ae819SStefano Zampini     }
5630674ae819SStefano Zampini   }
5631674ae819SStefano Zampini   /* assembling */
5632674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5633674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5634088faed8SStefano Zampini 
5635984c4197SStefano Zampini   /*
56366a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5637984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5638f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5639984c4197SStefano Zampini   */
5640674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5641674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5642026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5643984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5644984c4197SStefano Zampini     /* working stuff for GEQRF */
564581d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5646984c4197SStefano Zampini     PetscBLASInt lqr_work;
5647984c4197SStefano Zampini     /* working stuff for UNGQR */
5648984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5649984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5650984c4197SStefano Zampini     /* working stuff for TRTRS */
5651984c4197SStefano Zampini     PetscScalar  *trs_rhs;
56523f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5653984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5654984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5655984c4197SStefano Zampini     PetscScalar  *start_vals;
5656984c4197SStefano Zampini     /* working stuff for values insertion */
56574641a718SStefano Zampini     PetscBT      is_primal;
565864efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5659906d46d4SStefano Zampini     /* matrix sizes */
5660906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5661906d46d4SStefano Zampini     /* temporary change of basis */
5662906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5663cf5a6209SStefano Zampini     /* extra space for debugging */
5664cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5665984c4197SStefano Zampini 
5666906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5667906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
566816f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5669bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5670906d46d4SStefano Zampini     /* nonzeros for local mat */
5671bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
56721dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5673bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
56741dd7afcfSStefano Zampini     } else {
56751dd7afcfSStefano Zampini       const PetscInt *ii;
56761dd7afcfSStefano Zampini       PetscInt       n;
56771dd7afcfSStefano Zampini       PetscBool      flg_row;
56781dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
56791dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
56801dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
56811dd7afcfSStefano Zampini     }
56829162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5683a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
56849162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5685a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
56869162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5687a717540cSStefano Zampini         } else {
56889162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
56899162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5690a717540cSStefano Zampini         }
5691a717540cSStefano Zampini       }
5692a717540cSStefano Zampini     }
5693906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5694bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
56951dd7afcfSStefano Zampini     /* Set interior change in the matrix */
56961dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5697bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5698906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5699a717540cSStefano Zampini       }
57001dd7afcfSStefano Zampini     } else {
57011dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
57021dd7afcfSStefano Zampini       PetscScalar    *aa;
57031dd7afcfSStefano Zampini       PetscInt       n;
57041dd7afcfSStefano Zampini       PetscBool      flg_row;
57051dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
57061dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
57071dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
57081dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
57091dd7afcfSStefano Zampini       }
57101dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
57111dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
57121dd7afcfSStefano Zampini     }
5713a717540cSStefano Zampini 
5714a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5715a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5716a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5717a717540cSStefano Zampini     }
5718a717540cSStefano Zampini 
5719a717540cSStefano Zampini 
5720a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5721a717540cSStefano Zampini     /*
5722a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5723a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5724a717540cSStefano Zampini 
5725a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5726a717540cSStefano Zampini 
5727a6b551f4SStefano 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)
5728a6b551f4SStefano Zampini 
5729a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5730a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5731a717540cSStefano Zampini             |              ...                        |
5732a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5733a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5734a717540cSStefano Zampini 
5735a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5736a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5737a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5738a6b551f4SStefano Zampini 
5739a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5740a717540cSStefano Zampini     */
5741a717540cSStefano Zampini     if (qr_needed) {
5742984c4197SStefano Zampini       /* space to store Q */
5743854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
57444e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
57454e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5746984c4197SStefano Zampini       /* first we issue queries for optimal work */
57473f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
57483f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
57493f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5750984c4197SStefano Zampini       lqr_work = -1;
57513f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5752984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5753984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5754785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5755984c4197SStefano Zampini       lgqr_work = -1;
57563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
57573f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
57583f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
57593f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
57603f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
57613f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5762984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5763984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5764785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5765984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5766785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5767a717540cSStefano Zampini       /* allocating workspace for check */
5768a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5769cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5770a717540cSStefano Zampini       }
5771a717540cSStefano Zampini     }
5772984c4197SStefano Zampini     /* array to store whether a node is primal or not */
57734641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5774473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
57750e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
5776*eee23b56SStefano 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);
577739e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
577839e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
577939e2fb2aSStefano Zampini     }
578039e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5781984c4197SStefano Zampini 
5782a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
57839162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
57849162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
57854641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5786984c4197SStefano Zampini         /* get constraint info */
57879162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5788984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5789984c4197SStefano Zampini 
5790984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
57919162d606SStefano 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);
5792674ae819SStefano Zampini         }
5793984c4197SStefano Zampini 
5794fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5795a717540cSStefano Zampini 
5796a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5797a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
57989162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5799a717540cSStefano Zampini           }
5800984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
58019162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5802984c4197SStefano Zampini 
5803984c4197SStefano Zampini           /* compute QR decomposition of constraints */
58043f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
58053f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
58063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5807674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58083f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5809984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5810674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5811984c4197SStefano Zampini 
5812984c4197SStefano Zampini           /* explictly compute R^-T */
5813984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5814984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
58153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
58163f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
58173f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
58183f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5819984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58203f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5821984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5822984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5823984c4197SStefano Zampini 
5824a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
58253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
58263f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
58273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
58283f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5829984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58303f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5831984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5832984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5833984c4197SStefano Zampini 
5834984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5835984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5836984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
58373f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
58383f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
58393f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
58403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
58413f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
58423f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5843984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
58449162d606SStefano 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));
5845984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
58469162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5847984c4197SStefano Zampini 
5848984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
58499162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5850984c4197SStefano Zampini           /* insert cols for primal dofs */
5851984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5852984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
58539162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5854906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5855984c4197SStefano Zampini           }
5856984c4197SStefano Zampini           /* insert cols for dual dofs */
5857984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
58589162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5859984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
58609162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5861906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5862984c4197SStefano Zampini               j++;
5863674ae819SStefano Zampini             }
5864674ae819SStefano Zampini           }
5865984c4197SStefano Zampini 
5866984c4197SStefano Zampini           /* check change of basis */
5867984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5868984c4197SStefano Zampini             PetscInt   ii,jj;
5869984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5870c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5871c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5872c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5873c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5874c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5875c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5876984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5877cf5a6209SStefano 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));
5878984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5879984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5880984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5881cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5882cf5a6209SStefano Zampini                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
5883674ae819SStefano Zampini               }
5884674ae819SStefano Zampini             }
5885984c4197SStefano Zampini             if (!valid_qr) {
588622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5887984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5888984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5889cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5890cf5a6209SStefano 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]));
5891674ae819SStefano Zampini                   }
5892cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5893cf5a6209SStefano 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]));
5894984c4197SStefano Zampini                   }
5895984c4197SStefano Zampini                 }
5896984c4197SStefano Zampini               }
5897674ae819SStefano Zampini             } else {
589822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5899674ae819SStefano Zampini             }
5900674ae819SStefano Zampini           }
5901a717540cSStefano Zampini         } else { /* simple transformation block */
5902a717540cSStefano Zampini           PetscInt    row,col;
5903a6b551f4SStefano Zampini           PetscScalar val,norm;
5904a6b551f4SStefano Zampini 
5905a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
59069162d606SStefano 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));
5907a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
59089162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
59099162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5910bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
59119162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5912906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
59139162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5914a717540cSStefano Zampini             } else {
5915a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
59169162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5917a717540cSStefano Zampini                 if (row != col) {
59189162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5919a717540cSStefano Zampini                 } else {
59209162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5921a717540cSStefano Zampini                 }
5922906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5923a717540cSStefano Zampini               }
5924a717540cSStefano Zampini             }
5925a717540cSStefano Zampini           }
592698a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
592722d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5928a717540cSStefano Zampini           }
5929674ae819SStefano Zampini         }
5930984c4197SStefano Zampini       } else {
5931984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
59329162d606SStefano 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);
5933674ae819SStefano Zampini         }
5934674ae819SStefano Zampini       }
5935674ae819SStefano Zampini     }
5936a717540cSStefano Zampini 
5937a717540cSStefano Zampini     /* free workspace */
5938a717540cSStefano Zampini     if (qr_needed) {
5939984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5940cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5941984c4197SStefano Zampini       }
5942984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5943984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5944984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5945984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5946984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5947674ae819SStefano Zampini     }
5948a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5949906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5950906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5951906d46d4SStefano Zampini 
5952906d46d4SStefano Zampini     /* assembling of global change of variable */
595388c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5954bbb9e6c6SStefano Zampini       Mat      tmat;
595516f15bc4SStefano Zampini       PetscInt bs;
595616f15bc4SStefano Zampini 
5957906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5958906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5959bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5960bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5961bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5962bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
596316f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
596416f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5965906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5966bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5967bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5968bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5969bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5970bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5971e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5972e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5973bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5974bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
597588c03ad3SStefano Zampini 
5976906d46d4SStefano Zampini       /* check */
5977906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5978906d46d4SStefano Zampini         PetscReal error;
5979906d46d4SStefano Zampini         Vec       x,x_change;
5980906d46d4SStefano Zampini 
5981906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5982906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5983906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5984906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5985e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5986e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5987bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5988e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5989e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5990906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5991906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5992906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5993906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5994bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5995906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5996906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5997906d46d4SStefano Zampini       }
5998b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5999b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6000b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6001bf3a8328SStefano Zampini 
60029a962809SStefano Zampini         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");CHKERRQ(ierr);
6003b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6004ac632422SStefano Zampini           Mat                    S_new,tmat;
6005bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6006bbb9e6c6SStefano Zampini 
6007bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
60086816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6009bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6010bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6011bf3a8328SStefano Zampini             IS                     is_V;
6012b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6013b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6014b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6015b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6016b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6017bf3a8328SStefano Zampini           }
6018bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6019ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6020b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6021ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6022bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6023bf3a8328SStefano Zampini             const PetscScalar *array;
6024bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6025bf3a8328SStefano Zampini             PetscInt          i,n_V;
6026bf3a8328SStefano Zampini 
6027b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6028b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6029b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6030b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6031b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6032b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6033b087196eSStefano Zampini               PetscScalar val;
6034b087196eSStefano Zampini               PetscInt    idx;
6035b087196eSStefano Zampini 
6036b087196eSStefano Zampini               idx = idxs_V[i];
6037b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6038b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6039b087196eSStefano Zampini             }
6040b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6041b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6042bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6043bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6044bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6045bf3a8328SStefano Zampini           }
6046ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6047ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6048ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6049ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6050b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6051ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6052bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6053b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6054bf3a8328SStefano Zampini             }
6055ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6056ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6057ac632422SStefano Zampini           }
6058b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
605988c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6060b96c3477SStefano Zampini         }
6061c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6062b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6063c9db6a07SStefano Zampini           PetscInt i;
6064c9db6a07SStefano Zampini 
6065c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6066c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6067c9db6a07SStefano Zampini           }
6068c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6069c9db6a07SStefano Zampini         }
6070b96c3477SStefano Zampini       }
607116909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
607216909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
607316909a7fSStefano Zampini       } else {
6074906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
607516909a7fSStefano Zampini       }
60761dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
607727b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
607872b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
607972b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
608072b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
608172b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
608272b8c272SStefano Zampini     }
60831dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
608427b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6085b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6086b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6087906d46d4SStefano Zampini     } else {
60881dd7afcfSStefano Zampini       Mat benign_global = NULL;
608927b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
60901dd7afcfSStefano Zampini         Mat tmat;
60911dd7afcfSStefano Zampini 
60921dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
60931dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
60941dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
60951dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
60961dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
60971dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
60981dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60991dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
61001dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
61011dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
61021dd7afcfSStefano Zampini           Mat M;
61031dd7afcfSStefano Zampini 
61041dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
61051dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
61061dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
61071dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6108906d46d4SStefano Zampini         } else {
61091dd7afcfSStefano Zampini           Mat         eye;
61101dd7afcfSStefano Zampini           PetscScalar *array;
61111dd7afcfSStefano Zampini 
61121dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
61131dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
61141dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
61151dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6116906d46d4SStefano Zampini           }
61171dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
61181dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
61191dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
61201dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
61211dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
61221dd7afcfSStefano Zampini         }
61231dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
61241dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
61251dd7afcfSStefano Zampini       }
61261dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
61271dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
61281dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
612927b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
61301dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
61311dd7afcfSStefano Zampini       }
61321dd7afcfSStefano Zampini     }
613316909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
613416909a7fSStefano Zampini       IS             is_global;
613516909a7fSStefano Zampini       const PetscInt *gidxs;
613616909a7fSStefano Zampini 
613716909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
613816909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
613916909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
614016909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
614116909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
614216909a7fSStefano Zampini     }
61431dd7afcfSStefano Zampini   }
61441dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
61451dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6146b9b85e73SStefano Zampini   }
6147a717540cSStefano Zampini 
614872b8c272SStefano Zampini   if (!pcbddc->fake_change) {
61494f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
61504f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
61514f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
61524f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6153019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6154019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6155019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6156019a44ceSStefano Zampini     }
6157019a44ceSStefano Zampini 
6158019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6159727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6160727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
61619f47a83aSStefano 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);
6162c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
61630e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
61649f47a83aSStefano 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);
6165727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6166727cdba6SStefano Zampini       }
61670e6343abSStefano Zampini     }
6168727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6169b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
617072b8c272SStefano Zampini   }
617172b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6172727cdba6SStefano Zampini 
6173a717540cSStefano Zampini   /* flush dbg viewer */
6174b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6175b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6176b8ffe317SStefano Zampini   }
6177a717540cSStefano Zampini 
6178e310c8b4SStefano Zampini   /* free workspace */
6179a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
61804641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
618108122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
61829162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
61839162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
618408122e43SStefano Zampini   } else {
61859162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
61869162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
61879162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
618808122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
618908122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
61909162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
61919162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
619208122e43SStefano Zampini   }
6193674ae819SStefano Zampini   PetscFunctionReturn(0);
6194674ae819SStefano Zampini }
6195674ae819SStefano Zampini 
6196674ae819SStefano Zampini #undef __FUNCT__
6197674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
6198674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6199674ae819SStefano Zampini {
620071582508SStefano Zampini   ISLocalToGlobalMapping map;
6201674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6202674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
620314f95afaSStefano Zampini   PetscInt               ierr,i,N;
6204674ae819SStefano Zampini 
6205674ae819SStefano Zampini   PetscFunctionBegin;
62068af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6207b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
62088e61c736SStefano Zampini     /* Reset previously computed graph */
62098e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6210674ae819SStefano Zampini     /* Init local Graph struct */
62117fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
621271582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6213be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6214674ae819SStefano Zampini 
6215575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
62169a962809SStefano 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);
62179577ea80SStefano Zampini 
6218674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
6219d4d8cf7bSStefano Zampini     if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
62204d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
62214d379d7bSStefano Zampini       PetscInt  nvtxs;
6222e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6223674ae819SStefano Zampini 
62242fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
62252fffb893SStefano Zampini       if (flg_row) {
62264d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6227b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
62282fffb893SStefano Zampini       }
62292fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
6230674ae819SStefano Zampini     }
62319b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
62329b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6233674ae819SStefano Zampini     }
6234674ae819SStefano Zampini 
6235674ae819SStefano Zampini     /* Setup of Graph */
62364b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
623714f95afaSStefano 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);
6238674ae819SStefano Zampini 
62394f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
62404f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
62414f1b2e48SStefano Zampini       PetscInt *local_subs;
62424f1b2e48SStefano Zampini 
62434f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
62444f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
62454f1b2e48SStefano Zampini         const PetscInt *idxs;
62464f1b2e48SStefano Zampini         PetscInt       nl,j;
62474f1b2e48SStefano Zampini 
62484f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
62494f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
625071582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
62514f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
62524f1b2e48SStefano Zampini       }
62534f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
62544f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
62554f1b2e48SStefano Zampini     }
62568af8fcf9SStefano Zampini   }
62574f1b2e48SStefano Zampini 
6258cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6259674ae819SStefano Zampini     /* Graph's connected components analysis */
6260674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
626171582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
62628af8fcf9SStefano Zampini   }
6263674ae819SStefano Zampini   PetscFunctionReturn(0);
6264674ae819SStefano Zampini }
6265674ae819SStefano Zampini 
62669a7d3425SStefano Zampini #undef __FUNCT__
62679a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
62689a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
62699a7d3425SStefano Zampini {
62709a7d3425SStefano Zampini   PetscInt       i,j;
62719a7d3425SStefano Zampini   PetscScalar    *alphas;
62729a7d3425SStefano Zampini   PetscErrorCode ierr;
62739a7d3425SStefano Zampini 
62749a7d3425SStefano Zampini   PetscFunctionBegin;
6275785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
62769a7d3425SStefano Zampini   for (i=0;i<n;i++) {
62779a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6278669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6279669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6280669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
62819a7d3425SStefano Zampini   }
62829a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
62839a7d3425SStefano Zampini   PetscFunctionReturn(0);
62849a7d3425SStefano Zampini }
62859a7d3425SStefano Zampini 
6286e7931f94SStefano Zampini #undef __FUNCT__
628770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
628857de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6289e7931f94SStefano Zampini {
629057de7509SStefano Zampini   Mat            A;
6291e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6292e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
629352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
629452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
629527b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
629657de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
629727b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
629827b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
629927b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
630027b6a85dSStefano Zampini   MPI_Comm       subcomm;
630152e5ac9dSStefano Zampini   PetscErrorCode ierr;
6302a57a6d2fSStefano Zampini 
6303e7931f94SStefano Zampini   PetscFunctionBegin;
630457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
630557de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
630657de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
630757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
630857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
630957de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
631057de7509SStefano Zampini 
631157de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
631257de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
631357de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
631457de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
631557de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
631657de7509SStefano Zampini   im_active = !!(n);
631757de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
631857de7509SStefano Zampini   void_procs = size - active_procs;
631957de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
632057de7509SStefano Zampini   if (void_procs) {
632157de7509SStefano Zampini     PetscInt ncand;
632257de7509SStefano Zampini 
632357de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
632457de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
632557de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
632657de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
632757de7509SStefano Zampini       if (!procs_candidates[i]) {
632857de7509SStefano Zampini         procs_candidates[ncand++] = i;
632957de7509SStefano Zampini       }
633057de7509SStefano Zampini     }
633157de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
633257de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
633357de7509SStefano Zampini   }
633457de7509SStefano Zampini 
633514f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
633614f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
633714f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
633814f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
633914f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
634014f0bfb9SStefano Zampini     else dest = rank;
634157de7509SStefano Zampini     if (im_active) {
634257de7509SStefano Zampini       issize = 1;
634357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
634414f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
634557de7509SStefano Zampini       } else {
634614f0bfb9SStefano Zampini         isidx = dest;
634757de7509SStefano Zampini       }
634857de7509SStefano Zampini     } else {
634957de7509SStefano Zampini       issize = 0;
635057de7509SStefano Zampini       isidx = -1;
635157de7509SStefano Zampini     }
635257de7509SStefano Zampini     *n_subdomains = active_procs;
635357de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6354daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
635557de7509SStefano Zampini     PetscFunctionReturn(0);
635657de7509SStefano Zampini   }
6357c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6358c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
635927b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6360e7931f94SStefano Zampini 
6361e7931f94SStefano Zampini   /* Get info on mapping */
63623bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
63633bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6364e7931f94SStefano Zampini 
6365e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6366785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6367e7931f94SStefano Zampini   xadj[0] = 0;
6368e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6369785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6370785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
637127b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
637227b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
637327b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
637427b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6375e7931f94SStefano Zampini 
637627b6a85dSStefano Zampini   xadj_count = 0;
63772b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
637827b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
637927b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6380d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6381d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6382d023bfaeSStefano Zampini         xadj_count++;
638327b6a85dSStefano Zampini         break;
638427b6a85dSStefano Zampini       }
6385e7931f94SStefano Zampini     }
6386e7931f94SStefano Zampini   }
6387d023bfaeSStefano Zampini   xadj[1] = xadj_count;
638827b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
63893bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6390e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6391e7931f94SStefano Zampini 
63923837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6393e7931f94SStefano Zampini 
639427b6a85dSStefano Zampini   /* Restrict work on active processes only */
639527b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
639627b6a85dSStefano Zampini   if (void_procs) {
639727b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
639827b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
639927b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
640027b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
640127b6a85dSStefano Zampini   } else {
640227b6a85dSStefano Zampini     psubcomm = NULL;
640327b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
640427b6a85dSStefano Zampini   }
640527b6a85dSStefano Zampini 
640627b6a85dSStefano Zampini   v_wgt = NULL;
640727b6a85dSStefano Zampini   if (!color) {
6408e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6409e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6410e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6411c8587f34SStefano Zampini   } else {
641252e5ac9dSStefano Zampini     Mat             subdomain_adj;
641352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
641452e5ac9dSStefano Zampini     MatPartitioning partitioner;
641527b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
641652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
641757de7509SStefano Zampini     PetscMPIInt     size;
6418b0c7d250SStefano Zampini     PetscBool       aggregate;
6419b0c7d250SStefano Zampini 
642027b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
642127b6a85dSStefano Zampini     if (void_procs) {
642227b6a85dSStefano Zampini       PetscInt prank = rank;
6423785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
642427b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6425e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6426e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6427c8587f34SStefano Zampini       }
6428e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
642927b6a85dSStefano Zampini     } else {
643027b6a85dSStefano Zampini       oldranks = NULL;
643127b6a85dSStefano Zampini     }
6432b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
643327b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6434b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6435b0c7d250SStefano Zampini       PetscMPIInt nrank;
6436b0c7d250SStefano Zampini       PetscScalar *vals;
6437b0c7d250SStefano Zampini 
643827b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6439b0c7d250SStefano Zampini       lrows = 0;
6440b0c7d250SStefano Zampini       if (nrank<redprocs) {
6441b0c7d250SStefano Zampini         lrows = size/redprocs;
6442b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6443b0c7d250SStefano Zampini       }
644427b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6445b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6446b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6447b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6448b0c7d250SStefano Zampini       row = nrank;
6449b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6450b0c7d250SStefano Zampini       cols = adjncy;
6451b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6452b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6453b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6454b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6455b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
645652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
645752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
645852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6459b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
646027b6a85dSStefano Zampini       if (use_vwgt) {
646127b6a85dSStefano Zampini         Vec               v;
646227b6a85dSStefano Zampini         const PetscScalar *array;
646327b6a85dSStefano Zampini         PetscInt          nl;
646427b6a85dSStefano Zampini 
646527b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
646627b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
646727b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
646827b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
646927b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
647027b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
647127b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
647222db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
647327b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
647427b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
647527b6a85dSStefano Zampini       }
6476b0c7d250SStefano Zampini     } else {
647727b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
647827b6a85dSStefano Zampini       if (use_vwgt) {
647927b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
648027b6a85dSStefano Zampini         v_wgt[0] = local_size;
648127b6a85dSStefano Zampini       }
6482b0c7d250SStefano Zampini     }
648322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6484e7931f94SStefano Zampini 
6485e7931f94SStefano Zampini     /* Partition */
648627b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6487e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
648827b6a85dSStefano Zampini     if (v_wgt) {
6489e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6490c8587f34SStefano Zampini     }
649157de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
649257de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6493e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6494e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
649522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6496e7931f94SStefano Zampini 
649752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
64986583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
649952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
650052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
650157de7509SStefano Zampini     if (!aggregate) {
650257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
650327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
650427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
650527b6a85dSStefano Zampini #endif
650657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
650727b6a85dSStefano Zampini       } else if (oldranks) {
6508b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
650927b6a85dSStefano Zampini       } else {
651027b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
651157de7509SStefano Zampini       }
651228143c3dSStefano Zampini     } else {
6513b0c7d250SStefano Zampini       PetscInt    idxs[1];
6514b0c7d250SStefano Zampini       PetscMPIInt tag;
6515b0c7d250SStefano Zampini       MPI_Request *reqs;
6516b0c7d250SStefano Zampini 
6517b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6518b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6519b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
652027b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
652128143c3dSStefano Zampini       }
652227b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6523b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6524b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
652557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
652627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
652727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
652827b6a85dSStefano Zampini #endif
652957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
653027b6a85dSStefano Zampini       } else if (oldranks) {
6531b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
653227b6a85dSStefano Zampini       } else {
653327b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6534e7931f94SStefano Zampini       }
653557de7509SStefano Zampini     }
653652e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6537e7931f94SStefano Zampini     /* clean up */
6538e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
653952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6540e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6541e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6542e7931f94SStefano Zampini   }
654327b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
654457de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6545e7931f94SStefano Zampini 
6546e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6547e7931f94SStefano Zampini   i = 1;
654827b6a85dSStefano Zampini   if (!color) i=0;
654957de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6550e7931f94SStefano Zampini   PetscFunctionReturn(0);
6551e7931f94SStefano Zampini }
6552e7931f94SStefano Zampini 
6553e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6554e7931f94SStefano Zampini 
6555e7931f94SStefano Zampini #undef __FUNCT__
65561e0482f5SStefano Zampini #define __FUNCT__ "PCBDDCMatISSubassemble"
65571e0482f5SStefano 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[])
6558e7931f94SStefano Zampini {
655970cf5478SStefano Zampini   Mat                    local_mat;
6560e7931f94SStefano Zampini   IS                     is_sends_internal;
65619d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
65621ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
65639d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6564e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6565e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6566e7931f94SStefano Zampini   const PetscInt*        is_indices;
6567e7931f94SStefano Zampini   MatType                new_local_type;
6568e7931f94SStefano Zampini   /* buffers */
6569e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
657028143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
65719d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6572e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
65731ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6574e7931f94SStefano Zampini   /* MPI */
657528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
657628143c3dSStefano Zampini   PetscSubcomm           subcomm;
6577e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
657828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
657928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
65801ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
65811ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
65821ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6583e7931f94SStefano Zampini   PetscErrorCode         ierr;
6584e7931f94SStefano Zampini 
6585e7931f94SStefano Zampini   PetscFunctionBegin;
658657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6587e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
658828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
658957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
659057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
659157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
659257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
659357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
65941ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
65951ae86dd6SStefano Zampini   if (nvecs) {
65961ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
65971ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
65981ae86dd6SStefano Zampini   }
659957de7509SStefano Zampini   /* further checks */
6600e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6601e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6602e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6603e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6604e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
660557de7509SStefano Zampini   if (reuse && *mat_n) {
660670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
660757de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
660870cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
660928143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
661070cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
661170cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
661270cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
661370cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
661470cf5478SStefano Zampini   }
6615e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6616e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
661757de7509SStefano Zampini 
6618e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6619e7931f94SStefano Zampini   if (!is_sends) {
662028143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
662157de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6622c8587f34SStefano Zampini   } else {
6623e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6624e7931f94SStefano Zampini     is_sends_internal = is_sends;
6625c8587f34SStefano Zampini   }
6626e7931f94SStefano Zampini 
6627e7931f94SStefano Zampini   /* get comm */
6628a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6629e7931f94SStefano Zampini 
6630e7931f94SStefano Zampini   /* compute number of sends */
6631e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6632e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6633e7931f94SStefano Zampini 
6634e7931f94SStefano Zampini   /* compute number of receives */
6635e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6636785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6637e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6638e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6639e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6640e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6641e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6642e7931f94SStefano Zampini 
664328143c3dSStefano Zampini   /* restrict comm if requested */
664428143c3dSStefano Zampini   subcomm = 0;
664528143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
664628143c3dSStefano Zampini   if (restrict_comm) {
6647779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6648779c1cceSStefano Zampini 
664928143c3dSStefano Zampini     color = 0;
665053a05cb3SStefano Zampini     if (restrict_full) {
665153a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
665253a05cb3SStefano Zampini     } else {
665353a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
665453a05cb3SStefano Zampini     }
6655b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
665628143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
665728143c3dSStefano Zampini     /* check if reuse has been requested */
665857de7509SStefano Zampini     if (reuse) {
665928143c3dSStefano Zampini       if (*mat_n) {
666028143c3dSStefano Zampini         PetscMPIInt subcommsize2;
666128143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
666228143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
666328143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
666428143c3dSStefano Zampini       } else {
666528143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
666628143c3dSStefano Zampini       }
666728143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6668779c1cceSStefano Zampini       PetscMPIInt rank;
6669779c1cceSStefano Zampini 
6670779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
667128143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
667228143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
667328143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6674306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
667528143c3dSStefano Zampini     }
667628143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
667728143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
667828143c3dSStefano Zampini   } else {
667928143c3dSStefano Zampini     comm_n = comm;
668028143c3dSStefano Zampini   }
668128143c3dSStefano Zampini 
6682e7931f94SStefano Zampini   /* prepare send/receive buffers */
6683785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6684e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6685785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6686e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
668728143c3dSStefano Zampini   if (nis) {
6688854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
668928143c3dSStefano Zampini   }
6690e7931f94SStefano Zampini 
669128143c3dSStefano Zampini   /* Get data from local matrices */
66926c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6693e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6694e7931f94SStefano Zampini     /*
6695e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6696e7931f94SStefano Zampini        send_buffer_idxs should contain:
6697e7931f94SStefano Zampini        - MatType_PRIVATE type
6698e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6699e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6700e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6701e7931f94SStefano Zampini     */
67026c4ed002SBarry Smith   else {
6703e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
67043bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6705854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6706e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6707e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
67083bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6709e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
67103bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6711e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6712e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6713e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6714e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6715c8587f34SStefano Zampini     }
6716c8587f34SStefano Zampini   }
6717e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
671828143c3dSStefano Zampini   /* additional is (if any) */
671928143c3dSStefano Zampini   if (nis) {
672028143c3dSStefano Zampini     PetscMPIInt psum;
672128143c3dSStefano Zampini     PetscInt j;
672228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
672328143c3dSStefano Zampini       PetscInt plen;
672428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
672528143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
672628143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
672728143c3dSStefano Zampini     }
6728854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
672928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
673028143c3dSStefano Zampini       PetscInt plen;
673128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
673228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
673328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
673428143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
673528143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
673628143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
673728143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
673828143c3dSStefano Zampini     }
673928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
674028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
674128143c3dSStefano Zampini     }
674228143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
674328143c3dSStefano Zampini   }
674428143c3dSStefano Zampini 
6745e7931f94SStefano Zampini   buf_size_idxs = 0;
6746e7931f94SStefano Zampini   buf_size_vals = 0;
674728143c3dSStefano Zampini   buf_size_idxs_is = 0;
67481ae86dd6SStefano Zampini   buf_size_vecs = 0;
6749e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6750e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6751e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
675228143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
67531ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6754e7931f94SStefano Zampini   }
6755785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6756785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
675795ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
67581ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6759e7931f94SStefano Zampini 
6760e7931f94SStefano Zampini   /* get new tags for clean communications */
6761e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6762e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
676328143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
67641ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6765e7931f94SStefano Zampini 
6766e7931f94SStefano Zampini   /* allocate for requests */
6767785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6768785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
676995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
67701ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6771785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6772785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
677395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
67741ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6775e7931f94SStefano Zampini 
6776e7931f94SStefano Zampini   /* communications */
6777e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6778e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
677928143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
67801ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6781e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6782e7931f94SStefano Zampini     source_dest = onodes[i];
6783e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6784e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6785e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6786e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
678728143c3dSStefano Zampini     if (nis) {
678857de7509SStefano Zampini       source_dest = onodes_is[i];
678928143c3dSStefano 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);
679028143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
679128143c3dSStefano Zampini     }
67921ae86dd6SStefano Zampini     if (nvecs) {
67931ae86dd6SStefano Zampini       source_dest = onodes[i];
67941ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
67951ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
67961ae86dd6SStefano Zampini     }
6797e7931f94SStefano Zampini   }
6798e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6799e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6800e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6801e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
680228143c3dSStefano Zampini     if (nis) {
680328143c3dSStefano 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);
680428143c3dSStefano Zampini     }
68051ae86dd6SStefano Zampini     if (nvecs) {
68061ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
68071ae86dd6SStefano 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);
68081ae86dd6SStefano Zampini     }
6809e7931f94SStefano Zampini   }
6810e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6811e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6812e7931f94SStefano Zampini 
6813e7931f94SStefano Zampini   /* assemble new l2g map */
6814e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6815e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
68169d30be91SStefano Zampini   new_local_rows = 0;
6817e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
68189d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6819e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6820e7931f94SStefano Zampini   }
68219d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6822e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
68239d30be91SStefano Zampini   new_local_rows = 0;
6824e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
68259d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
68269d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6827e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6828e7931f94SStefano Zampini   }
68299d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
68309d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6831e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6832e7931f94SStefano Zampini 
6833e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6834e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6835e7931f94SStefano 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) */
6836e7931f94SStefano Zampini   if (n_recvs) {
683728143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6838e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6839e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6840e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6841e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6842e7931f94SStefano Zampini         break;
6843e7931f94SStefano Zampini       }
6844e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6845e7931f94SStefano Zampini     }
6846e7931f94SStefano Zampini     switch (new_local_type_private) {
684728143c3dSStefano Zampini       case MATDENSE_PRIVATE:
684828143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6849e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6850e7931f94SStefano Zampini           bs = 1;
685128143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
685228143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
685328143c3dSStefano Zampini           bs = 1;
685428143c3dSStefano Zampini         }
6855e7931f94SStefano Zampini         break;
6856e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6857e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6858e7931f94SStefano Zampini         bs = 1;
6859e7931f94SStefano Zampini         break;
6860e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6861e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6862e7931f94SStefano Zampini         break;
6863e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6864e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6865e7931f94SStefano Zampini         break;
6866e7931f94SStefano Zampini       default:
68679d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6868e7931f94SStefano Zampini         break;
6869e7931f94SStefano Zampini     }
687028143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
687128143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
687228143c3dSStefano Zampini     bs = 1;
6873e7931f94SStefano Zampini   }
6874e7931f94SStefano Zampini 
687570cf5478SStefano Zampini   /* create MATIS object if needed */
687657de7509SStefano Zampini   if (!reuse) {
6877e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6878e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
687970cf5478SStefano Zampini   } else {
688070cf5478SStefano Zampini     /* it also destroys the local matrices */
688157de7509SStefano Zampini     if (*mat_n) {
688270cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
688357de7509SStefano Zampini     } else { /* this is a fake object */
688457de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
688557de7509SStefano Zampini     }
688670cf5478SStefano Zampini   }
688770cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6888e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
68899d30be91SStefano Zampini 
68909d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
68919d30be91SStefano Zampini 
68929d30be91SStefano Zampini   /* Global to local map of received indices */
68939d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
68949d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
68959d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
68969d30be91SStefano Zampini 
68979d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
68989d30be91SStefano Zampini   buf_size_idxs = 0;
68999d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
69009d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
69019d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
69029d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
69039d30be91SStefano Zampini   }
69049d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
69059d30be91SStefano Zampini 
69069d30be91SStefano Zampini   /* set preallocation */
69079d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
69089d30be91SStefano Zampini   if (!newisdense) {
69099d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
69109d30be91SStefano Zampini 
69119d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
69129d30be91SStefano Zampini     if (n_recvs) {
69139d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
69149d30be91SStefano Zampini     }
69159d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
69169d30be91SStefano Zampini       PetscInt j;
69179d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
69189d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
69199d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
69209d30be91SStefano Zampini         }
69219d30be91SStefano Zampini       } else {
69229d30be91SStefano Zampini         /* TODO */
69239d30be91SStefano Zampini       }
69249d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
69259d30be91SStefano Zampini     }
69269d30be91SStefano Zampini     if (new_local_nnz) {
69279d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
69289d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
69299d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
69309d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
69319d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
69329d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
69339d30be91SStefano Zampini     } else {
69349d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
69359d30be91SStefano Zampini     }
69369d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
69379d30be91SStefano Zampini   } else {
69389d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
69399d30be91SStefano Zampini   }
6940e7931f94SStefano Zampini 
6941e7931f94SStefano Zampini   /* set values */
6942e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
69439d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6944e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6945e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6946e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
69479d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6948e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6949e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6950e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
695128143c3dSStefano Zampini     } else {
695228143c3dSStefano Zampini       /* TODO */
6953e7931f94SStefano Zampini     }
6954e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6955e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6956e7931f94SStefano Zampini   }
6957e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6958e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
695970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
696070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69619d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6962e7931f94SStefano Zampini 
6963dfd14d43SStefano Zampini #if 0
696428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6965e7931f94SStefano Zampini     Vec       lvec,rvec;
6966e7931f94SStefano Zampini     PetscReal infty_error;
6967e7931f94SStefano Zampini 
69682a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6969e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6970e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6971e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
697270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6973e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6974e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6975e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6976e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6977e7931f94SStefano Zampini   }
697828143c3dSStefano Zampini #endif
6979e7931f94SStefano Zampini 
698028143c3dSStefano Zampini   /* assemble new additional is (if any) */
698128143c3dSStefano Zampini   if (nis) {
698228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
698328143c3dSStefano Zampini 
698428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6985854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
698628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
698728143c3dSStefano Zampini     psum = 0;
698828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
698928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
699028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
699128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
699228143c3dSStefano Zampini         psum += plen;
699328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
699428143c3dSStefano Zampini       }
699528143c3dSStefano Zampini     }
6996854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6997854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
699828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
699928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
700028143c3dSStefano Zampini     }
700128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
700228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
700328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
700428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
700528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
700628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
700728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
700828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
700928143c3dSStefano Zampini       }
701028143c3dSStefano Zampini     }
701128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
701228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
701328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
701428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
701528143c3dSStefano Zampini     }
701628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
701728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
701828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
701928143c3dSStefano Zampini   }
7020e7931f94SStefano Zampini   /* free workspace */
702128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7022e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7023e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7024e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7025e7931f94SStefano Zampini   if (isdense) {
7026e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7027e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
7028e7931f94SStefano Zampini   } else {
7029e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7030e7931f94SStefano Zampini   }
703128143c3dSStefano Zampini   if (nis) {
703228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
703328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
703428143c3dSStefano Zampini   }
70351ae86dd6SStefano Zampini 
70361ae86dd6SStefano Zampini   if (nvecs) {
70371ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
70381ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
70391ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
70401ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
70411ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
70421ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
70431ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
70441ae86dd6SStefano Zampini     /* set values */
70451ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
70461ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
70471ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
70481ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
70491ae86dd6SStefano Zampini       PetscInt j;
70501ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
70511ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
70521ae86dd6SStefano Zampini       }
70531ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
70541ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
70551ae86dd6SStefano Zampini     }
70561ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
70571ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
70581ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
70591ae86dd6SStefano Zampini   }
70601ae86dd6SStefano Zampini 
70611ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
70621ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7063e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7064e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
70651ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
706628143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7067e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7068e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
70691ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
707028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7071e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7072e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7073e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7074e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7075e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
707628143c3dSStefano Zampini   if (nis) {
707728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
707828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
707928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
708028143c3dSStefano Zampini   }
708128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
708228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
708328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
708428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
708528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
708628143c3dSStefano Zampini     }
70871ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
70881ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
70891ae86dd6SStefano Zampini     }
709053a05cb3SStefano Zampini     *mat_n = NULL;
709128143c3dSStefano Zampini   }
7092e7931f94SStefano Zampini   PetscFunctionReturn(0);
7093e7931f94SStefano Zampini }
7094a57a6d2fSStefano Zampini 
709512edc857SStefano Zampini /* temporary hack into ksp private data structure */
7096af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
709712edc857SStefano Zampini 
7098c8587f34SStefano Zampini #undef __FUNCT__
7099c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
7100c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7101c8587f34SStefano Zampini {
7102c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7103c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
710420a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
71051ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
71061e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
71079881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
710820a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
71096e683305SStefano Zampini   IS                     coarse_is,*isarray;
71106e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
711130368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7112f9eb5b7dSStefano Zampini   PC                     pc_temp;
7113c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7114c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7115f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
71164f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
71171e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
711868457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
711922bc73bbSStefano Zampini   PetscScalar            *array;
712057de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
712157de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
71229881197aSStefano Zampini   PetscErrorCode         ierr;
7123fdc09c96SStefano Zampini 
7124c8587f34SStefano Zampini   PetscFunctionBegin;
7125c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
712668457ee5SStefano 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 */
7127fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
71285a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
7129fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7130f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7131f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7132f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7133fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
713451bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
713551bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7136dc4bcba2SStefano Zampini         PC        pc;
7137dc4bcba2SStefano Zampini         PetscBool isbddc;
7138dc4bcba2SStefano Zampini 
7139dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
7140dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
7141dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
7142dc4bcba2SStefano Zampini         if (isbddc) {
714363c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
714463c961adSStefano Zampini         } else {
7145727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
714663c961adSStefano Zampini         }
7147fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7148fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7149fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7150f4ddd8eeSStefano Zampini       }
7151fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7152fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7153f4ddd8eeSStefano Zampini     }
715470cf5478SStefano Zampini     /* reset any subassembling information */
715557de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
715670cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
715757de7509SStefano Zampini     }
71586e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7159fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7160f4ddd8eeSStefano Zampini   }
716157de7509SStefano Zampini   /* assemble coarse matrix */
716257de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
716357de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
716457de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
716557de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
716618a45a71SStefano Zampini   } else {
716757de7509SStefano Zampini     coarse_mat = NULL;
716857de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
71696e683305SStefano Zampini   }
7170e7931f94SStefano Zampini 
7171abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7172abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7173abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7174abbbba34SStefano Zampini 
7175abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
717622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
717722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
717822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
717922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7180e176bc59SStefano 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);
71816e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
71826e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
71836e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7184abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7185abbbba34SStefano Zampini 
718657de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
718757de7509SStefano Zampini   im_active = !!(pcis->n);
718857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
718957de7509SStefano Zampini 
719014f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
719157de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
719257de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
719357de7509SStefano Zampini   coarse_mat_is = NULL;
719457de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
719557de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
71961ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
719757de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
719857de7509SStefano Zampini   if (multilevel_requested) {
719957de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
720057de7509SStefano Zampini     restr = PETSC_FALSE;
720157de7509SStefano Zampini     full_restr = PETSC_FALSE;
720257de7509SStefano Zampini   } else {
720357de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
720457de7509SStefano Zampini     restr = PETSC_TRUE;
720557de7509SStefano Zampini     full_restr = PETSC_TRUE;
720657de7509SStefano Zampini   }
72074b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
720857de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
720957de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7210a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
721137eada30SStefano Zampini       ierr = MatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7212a198735bSStefano Zampini     } else {
7213a198735bSStefano Zampini       PetscMPIInt size,rank;
7214a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
7215a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
7216a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
7217a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7218a198735bSStefano Zampini     }
721957de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
722057de7509SStefano Zampini     PetscInt    psum;
722157de7509SStefano Zampini     PetscMPIInt size;
722257de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
722357de7509SStefano Zampini     else psum = 0;
722457de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
722557de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
722657de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
722757de7509SStefano Zampini   }
722857de7509SStefano Zampini   /* determine if we can go multilevel */
722957de7509SStefano Zampini   if (multilevel_requested) {
723057de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
723157de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
723257de7509SStefano Zampini   }
723357de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
723457de7509SStefano Zampini 
7235e4d548c7SStefano Zampini   /* dump subassembling pattern */
7236e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7237e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7238e4d548c7SStefano Zampini   }
7239e4d548c7SStefano Zampini 
72406e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
72411e0482f5SStefano Zampini   nedcfield = -1;
72421e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
72436e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
72446e683305SStefano Zampini     const PetscInt         *idxs;
72456e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
72466e683305SStefano Zampini 
72476e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
72480be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
72496e683305SStefano Zampini     /* allocate space for temporary storage */
7250854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7251854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
72526e683305SStefano Zampini     /* allocate for IS array */
72536e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
72541e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
72551e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
72561e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
72571e0482f5SStefano Zampini       } else {
72581e0482f5SStefano Zampini         nedcfield = 0;
72591e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
72601e0482f5SStefano Zampini         nisdofs = 1;
72611e0482f5SStefano Zampini       }
72621e0482f5SStefano Zampini     }
72636e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
726427b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
726530368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7266854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
72676e683305SStefano Zampini     /* dofs splitting */
72686e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
72696e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
72701e0482f5SStefano Zampini       if (nedcfield != i) {
72716e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
72726e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
72736e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
72746e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
72751e0482f5SStefano Zampini       } else {
72761e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
72771e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
72781e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7279*eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
72801e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
72811e0482f5SStefano Zampini       }
72826e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
728330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
72846e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
72856e683305SStefano Zampini     }
72866e683305SStefano Zampini     /* neumann boundaries */
72876e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
72886e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
72896e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
72906e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
72916e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
72926e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
72936e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
729430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
72956e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
72966e683305SStefano Zampini     }
72976e683305SStefano Zampini     /* free memory */
72986e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
72996e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
73006e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
73016e683305SStefano Zampini   } else {
73026e683305SStefano Zampini     nis = 0;
73036e683305SStefano Zampini     nisdofs = 0;
73046e683305SStefano Zampini     nisneu = 0;
730530368db7SStefano Zampini     nisvert = 0;
73066e683305SStefano Zampini     isarray = NULL;
73076e683305SStefano Zampini   }
73086e683305SStefano Zampini   /* destroy no longer needed map */
73096e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
73106e683305SStefano Zampini 
731157de7509SStefano Zampini   /* subassemble */
731257de7509SStefano Zampini   if (multilevel_allowed) {
73131ae86dd6SStefano Zampini     Vec       vp[1];
73141ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
731557de7509SStefano Zampini     PetscBool reuse,reuser;
73161ae86dd6SStefano Zampini 
731757de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
731857de7509SStefano Zampini     else reuse = PETSC_FALSE;
731957de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
73201ae86dd6SStefano Zampini     vp[0] = NULL;
73211ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
73221ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
73231ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
73241ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
73251ae86dd6SStefano Zampini       nvecs = 1;
73261ae86dd6SStefano Zampini 
73271ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7328a198735bSStefano Zampini         Mat      B,loc_divudotp;
73291ae86dd6SStefano Zampini         Vec      v,p;
73301ae86dd6SStefano Zampini         IS       dummy;
73311ae86dd6SStefano Zampini         PetscInt np;
73321ae86dd6SStefano Zampini 
7333a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7334a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
73351ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
7336a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
73371ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
73381ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
73391ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
73401ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
73411ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
73421ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
73431ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
73441ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
73451ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
73461ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
73471ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
73481ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
734974e2c79eSStefano Zampini       }
73501ae86dd6SStefano Zampini     }
73511ae86dd6SStefano Zampini     if (reuser) {
73521e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
735374e2c79eSStefano Zampini     } else {
73541e0482f5SStefano 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);
73551ae86dd6SStefano Zampini     }
73561ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
73571ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
73581ae86dd6SStefano Zampini       PetscInt    nl;
73591ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
73601ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
73611ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
73621ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
73631ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
73641ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
73651ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
73661ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7367a198735bSStefano Zampini     } else {
7368a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
73691ae86dd6SStefano Zampini     }
73701ae86dd6SStefano Zampini   } else {
73711e0482f5SStefano 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);
73726e683305SStefano Zampini   }
737357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
737457de7509SStefano Zampini     PetscMPIInt size;
7375f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
737657de7509SStefano Zampini     if (!multilevel_allowed) {
737757de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
73786e683305SStefano Zampini     } else {
737957de7509SStefano Zampini       Mat A;
7380779c1cceSStefano Zampini 
738157de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
738257de7509SStefano Zampini       if (coarse_mat_is) {
738357de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
738457de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
738557de7509SStefano Zampini         coarse_mat = coarse_mat_is;
738657de7509SStefano Zampini       }
738757de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
738857de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
738957de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7390779c1cceSStefano Zampini     }
7391779c1cceSStefano Zampini   }
739257de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
739357de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
73946e683305SStefano Zampini 
73956e683305SStefano Zampini   /* create local to global scatters for coarse problem */
739668457ee5SStefano Zampini   if (compute_vecs) {
73976e683305SStefano Zampini     PetscInt lrows;
73986e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
739957de7509SStefano Zampini     if (coarse_mat) {
740057de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
74016e683305SStefano Zampini     } else {
74026e683305SStefano Zampini       lrows = 0;
74036e683305SStefano Zampini     }
74046e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
74056e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
74066e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
74076e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
74086e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
74096e683305SStefano Zampini   }
74106e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7411c8587f34SStefano Zampini 
7412f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7413f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7414f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7415f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7416f9eb5b7dSStefano Zampini   } else {
7417f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7418f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7419c8587f34SStefano Zampini   }
7420c8587f34SStefano Zampini 
74216e683305SStefano Zampini   /* print some info if requested */
74226e683305SStefano Zampini   if (pcbddc->dbg_flag) {
74236e683305SStefano Zampini     if (!multilevel_allowed) {
74246e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
74256e683305SStefano Zampini       if (multilevel_requested) {
74266e683305SStefano 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);
74276e683305SStefano Zampini       } else if (pcbddc->max_levels) {
74286e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
74296e683305SStefano Zampini       }
74306e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74316e683305SStefano Zampini     }
74326e683305SStefano Zampini   }
74336e683305SStefano Zampini 
74341e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
74351e0482f5SStefano Zampini   coarseG = NULL;
74361e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
74371e0482f5SStefano Zampini     MPI_Comm ccomm;
74381e0482f5SStefano Zampini     if (coarse_mat) {
74391e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
74401e0482f5SStefano Zampini     } else {
74411e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
74421e0482f5SStefano Zampini     }
74431e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
74441e0482f5SStefano Zampini   }
74451e0482f5SStefano Zampini 
7446f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
744757de7509SStefano Zampini   if (coarse_mat) {
74486a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
74496e683305SStefano Zampini     if (pcbddc->dbg_flag) {
745057de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
74516e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
74526e683305SStefano Zampini     }
7453f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7454312be037SStefano Zampini       char prefix[256],str_level[16];
7455e604994aSStefano Zampini       size_t len;
74561e0482f5SStefano Zampini 
745757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7458422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7459c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7460f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
746157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7462c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
74636e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7464c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
74651e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
7466c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7467e604994aSStefano Zampini       /* prefix */
7468e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7469e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7470e604994aSStefano Zampini       if (!pcbddc->current_level) {
7471e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7472e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7473c8587f34SStefano Zampini       } else {
7474e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7475312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7476312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
747734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7478312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7479e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7480e604994aSStefano Zampini       }
7481e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
74823e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
74833e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
74843e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
74853e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7486f9eb5b7dSStefano Zampini       /* allow user customization */
7487f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
74883e3c6dadSStefano Zampini     }
74893e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
749051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
74913e3c6dadSStefano Zampini     if (nisdofs) {
74923e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
74933e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
74943e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
74953e3c6dadSStefano Zampini       }
74963e3c6dadSStefano Zampini     }
74973e3c6dadSStefano Zampini     if (nisneu) {
74983e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
74993e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7500312be037SStefano Zampini     }
750130368db7SStefano Zampini     if (nisvert) {
750230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
750330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
750430368db7SStefano Zampini     }
75051e0482f5SStefano Zampini     if (coarseG) {
75061e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
75071e0482f5SStefano Zampini     }
7508f9eb5b7dSStefano Zampini 
7509f9eb5b7dSStefano Zampini     /* get some info after set from options */
7510f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7511f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
75124f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
75136e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7514f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7515f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7516f9eb5b7dSStefano Zampini     }
751739f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
75184f3a063dSStefano Zampini     if (isredundant) {
75194f3a063dSStefano Zampini       KSP inner_ksp;
75204f3a063dSStefano Zampini       PC  inner_pc;
75214f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
75224f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
75234f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
75244f3a063dSStefano Zampini     }
7525f9eb5b7dSStefano Zampini 
752657de7509SStefano Zampini     /* parameters which miss an API */
752757de7509SStefano Zampini     if (isbddc) {
7528720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7529720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
753057de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
753127b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
753227b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7533a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7534a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7535a198735bSStefano Zampini         IS                     row,col;
7536a198735bSStefano Zampini         const PetscInt         *gidxs;
7537a198735bSStefano Zampini         PetscInt               n,st,M,N;
7538a198735bSStefano Zampini 
7539a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7540a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7541a198735bSStefano Zampini         st = st-n;
7542a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7543a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7544a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7545a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7546a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7547a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7548a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7549a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7550a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7551a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7552a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7553a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7554a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7555a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7556a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7557a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7558a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7559a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7560a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7561a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
75628ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7563a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7564720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
756559e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7566720d30f9SStefano Zampini       }
7567d4d8cf7bSStefano Zampini     }
75689881197aSStefano Zampini 
75693301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
75705a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
75713301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
75723301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
75733301b35fSStefano Zampini     }
75743301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
75753301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
75763301b35fSStefano Zampini     }
75773301b35fSStefano Zampini     if (pc->pmat->spd_set) {
75783301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
75793301b35fSStefano Zampini     }
758027b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
758127b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
758227b6a85dSStefano Zampini     }
75836e683305SStefano Zampini     /* set operators */
75845f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
75856e683305SStefano Zampini     if (pcbddc->dbg_flag) {
75866e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
75876e683305SStefano Zampini     }
75886e683305SStefano Zampini   }
75891e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
75906e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7591b1ecc7b1SStefano Zampini #if 0
7592b9b85e73SStefano Zampini   {
7593b9b85e73SStefano Zampini     PetscViewer viewer;
7594b9b85e73SStefano Zampini     char filename[256];
7595b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7596b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
75976a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7598b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7599f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7600b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7601b9b85e73SStefano Zampini   }
7602b9b85e73SStefano Zampini #endif
7603f9eb5b7dSStefano Zampini 
760498a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
760598a51de6SStefano Zampini     Vec crhs,csol;
760604708bb6SStefano Zampini 
7607f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7608f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7609f347579bSStefano Zampini     if (!csol) {
76102a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7611f9eb5b7dSStefano Zampini     }
7612f347579bSStefano Zampini     if (!crhs) {
76132a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7614f347579bSStefano Zampini     }
7615b0f5fe93SStefano Zampini   }
76161ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7617b0f5fe93SStefano Zampini 
7618b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7619b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7620b0f5fe93SStefano Zampini 
7621b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
76224f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
76234f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
76244f1b2e48SStefano Zampini     }
7625b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7626b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7627b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7628b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7629b0f5fe93SStefano Zampini     if (coarse_mat) {
7630b0f5fe93SStefano Zampini       Vec         nullv;
7631b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7632b0f5fe93SStefano Zampini       PetscInt    nl;
7633b0f5fe93SStefano Zampini 
7634b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7635b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7636b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7637b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7638b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7639b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7640b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7641b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7642b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7643b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7644b0f5fe93SStefano Zampini     }
7645b0f5fe93SStefano Zampini   }
7646b0f5fe93SStefano Zampini 
7647b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7648b0f5fe93SStefano Zampini     PetscBool ispreonly;
7649b0f5fe93SStefano Zampini 
7650b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7651b0f5fe93SStefano Zampini       PetscBool isnull;
7652b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7653bef83e63SStefano Zampini       if (isnull) {
7654b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7655b0f5fe93SStefano Zampini       }
7656bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7657b0f5fe93SStefano Zampini     }
7658b0f5fe93SStefano Zampini     /* setup coarse ksp */
7659b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7660cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7661cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
76626e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7663c8587f34SStefano Zampini       KSP       check_ksp;
76642b510759SStefano Zampini       KSPType   check_ksp_type;
7665c8587f34SStefano Zampini       PC        check_pc;
76666e683305SStefano Zampini       Vec       check_vec,coarse_vec;
76676a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
76682b510759SStefano Zampini       PetscInt  its;
76696e683305SStefano Zampini       PetscBool compute_eigs;
76706e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
76716e683305SStefano Zampini       PetscInt  neigs;
76728e185a42SStefano Zampini       const char *prefix;
7673c8587f34SStefano Zampini 
76742b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
76756e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7676422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
767723ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7678f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7679e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7680e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7681e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
76822b510759SStefano Zampini       if (ispreonly) {
76832b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
76846e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
76852b510759SStefano Zampini       } else {
7686cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
76876e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7688c8587f34SStefano Zampini       }
7689c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
76906e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
76916e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
76926e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7693a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7694a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7695a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7696a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7697c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7698c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7699c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7700c8587f34SStefano Zampini       /* create random vec */
77012701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7702c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
77036e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7704c8587f34SStefano Zampini       /* solve coarse problem */
77056e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7706cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
77076e683305SStefano Zampini       if (compute_eigs) {
7708854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7709854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
77106e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
77111ae86dd6SStefano Zampini         if (neigs) {
77126e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
77136e683305SStefano Zampini           lambda_min = eigs_r[0];
77146e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
77152701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
77162701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7717cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7718cbcc2c2aSStefano Zampini             }
7719c8587f34SStefano Zampini           }
7720c8587f34SStefano Zampini         }
77211ae86dd6SStefano Zampini       }
7722cbcc2c2aSStefano Zampini 
7723c8587f34SStefano Zampini       /* check coarse problem residual error */
77246e683305SStefano Zampini       if (pcbddc->dbg_flag) {
77256e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
77266e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
77276e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7728c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
77296e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
77306e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7731779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
77326e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
77336e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
77346e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
77356e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7736b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7737b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7738b0f5fe93SStefano Zampini         }
77396e683305SStefano Zampini         if (compute_eigs) {
77406e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
7741b03ebc13SStefano Zampini           KSPConvergedReason reason;
7742deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7743c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
7744b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
77456e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
7746b03ebc13SStefano 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);
77476e683305SStefano Zampini           for (i=0;i<neigs;i++) {
77486e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7749c8587f34SStefano Zampini           }
77506e683305SStefano Zampini         }
77516e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
77526e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
77536e683305SStefano Zampini       }
7754e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
77552701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7756c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
77576e683305SStefano Zampini       if (compute_eigs) {
77586e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
77596e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7760c8587f34SStefano Zampini       }
77616e683305SStefano Zampini     }
77626e683305SStefano Zampini   }
7763bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7764cbcc2c2aSStefano Zampini   /* print additional info */
7765cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
77666e683305SStefano Zampini     /* waits until all processes reaches this point */
77676e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7768cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7769cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7770cbcc2c2aSStefano Zampini   }
7771cbcc2c2aSStefano Zampini 
77722b510759SStefano Zampini   /* free memory */
7773fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7774c8587f34SStefano Zampini   PetscFunctionReturn(0);
7775c8587f34SStefano Zampini }
7776674ae819SStefano Zampini 
7777f34684f1SStefano Zampini #undef __FUNCT__
7778f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7779f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7780f34684f1SStefano Zampini {
7781f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7782f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7783f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7784dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7785dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
778673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7787dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7788f34684f1SStefano Zampini   PetscErrorCode ierr;
7789f34684f1SStefano Zampini 
7790f34684f1SStefano Zampini   PetscFunctionBegin;
7791f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
77926c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7793dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
77943bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7795dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7796dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
77976583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7798dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7799dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7800dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
78016c4ed002SBarry 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);
7802dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7803dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7804dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7805dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7806dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7807f34684f1SStefano Zampini 
7808f34684f1SStefano Zampini   /* check numbering */
7809f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7810019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7811dc456d91SStefano Zampini     PetscInt    i;
7812b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7813f34684f1SStefano Zampini 
7814f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7815f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7816f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
78171575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7818019a44ceSStefano Zampini     /* counter */
7819019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7820019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7821019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7822019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7823019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7824019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7825f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7826f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7827727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7828f34684f1SStefano Zampini     }
7829f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7830f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7831f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7832e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7833e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7834e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7835e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7836f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7837019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7838f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7839019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
78402c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
784175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7842b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
78432c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
78442c66d082SStefano 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);
7845f34684f1SStefano Zampini       }
7846f34684f1SStefano Zampini     }
7847019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7848b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7849f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7850f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7851f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7852f34684f1SStefano Zampini     }
7853f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7854f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7855e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7856e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7857f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7858f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7859b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7860ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7861ca8b9ea9SStefano Zampini 
7862ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
78633bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7864f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7865f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7866f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7867f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
78684bc2dc4bSStefano 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);
7869f34684f1SStefano Zampini       }
7870f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7871ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7872f34684f1SStefano Zampini     }
7873f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
78741575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7875302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7876f34684f1SStefano Zampini   }
78778bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7878f34684f1SStefano Zampini   /* get back data */
7879f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7880f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7881674ae819SStefano Zampini   PetscFunctionReturn(0);
7882674ae819SStefano Zampini }
7883674ae819SStefano Zampini 
7884e456f2a8SStefano Zampini #undef __FUNCT__
7885e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7886a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7887e456f2a8SStefano Zampini {
7888e456f2a8SStefano Zampini   IS             localis_t;
7889a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7890e456f2a8SStefano Zampini   PetscScalar    *vals;
7891e456f2a8SStefano Zampini   PetscErrorCode ierr;
7892e456f2a8SStefano Zampini 
7893e456f2a8SStefano Zampini   PetscFunctionBegin;
7894a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7895e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7896854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7897e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7898e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7899a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7900a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
79011035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7902a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
79031035eff8SStefano Zampini   }
7904a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7905e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7906e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7907a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7908a7dc3881SStefano Zampini   /* now compute set in local ordering */
7909a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7910a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7911a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7912a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7913a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7914ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7915e456f2a8SStefano Zampini       lsize++;
7916e456f2a8SStefano Zampini     }
7917e456f2a8SStefano Zampini   }
7918854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7919a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7920ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7921e456f2a8SStefano Zampini       idxs[lsize++] = i;
7922e456f2a8SStefano Zampini     }
7923e456f2a8SStefano Zampini   }
7924a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7925a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7926e456f2a8SStefano Zampini   *localis = localis_t;
7927e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7928e456f2a8SStefano Zampini }
7929906d46d4SStefano Zampini 
7930b96c3477SStefano Zampini #undef __FUNCT__
7931b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
793208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7933b96c3477SStefano Zampini {
7934a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7935b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7936b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7937a64f4aa4SStefano Zampini   Mat                 S_j;
7938b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7939b96c3477SStefano Zampini   PetscBool           free_used_adj;
7940b96c3477SStefano Zampini   PetscErrorCode      ierr;
7941b96c3477SStefano Zampini 
7942b96c3477SStefano Zampini   PetscFunctionBegin;
7943b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7944b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
794508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7946b96c3477SStefano Zampini     used_xadj = NULL;
7947b96c3477SStefano Zampini     used_adjncy = NULL;
7948b96c3477SStefano Zampini   } else {
794908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
795008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
795108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
795208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7953b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7954b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7955b96c3477SStefano Zampini     } else {
79562fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7957b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7958b96c3477SStefano Zampini       PetscInt       nvtxs;
7959b96c3477SStefano Zampini 
79602fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
79612fffb893SStefano Zampini       if (flg_row) {
7962b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7963b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7964b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7965b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
79662fffb893SStefano Zampini       } else {
79672fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
79682fffb893SStefano Zampini         used_xadj = NULL;
79692fffb893SStefano Zampini         used_adjncy = NULL;
79702fffb893SStefano Zampini       }
79712fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7972b96c3477SStefano Zampini     }
7973b96c3477SStefano Zampini   }
7974d5574798SStefano Zampini 
7975d5574798SStefano Zampini   /* setup sub_schurs data */
7976a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7977df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7978df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7979a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
798091af6908SStefano 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);
7981a64f4aa4SStefano Zampini   } else {
79826816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
79834d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7984a3df083aSStefano Zampini     PetscInt  benign_n;
798572b8c272SStefano Zampini     Mat       change = NULL;
79869d54b7f4SStefano Zampini     Vec       scaling = NULL;
798772b8c272SStefano Zampini     IS        change_primal = NULL;
7988a3df083aSStefano Zampini 
79895feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
79905feab87aSStefano Zampini       PetscInt n_vertices;
79915feab87aSStefano Zampini 
79925feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
79932034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
79945feab87aSStefano Zampini     }
799504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
799604708bb6SStefano Zampini     if (!isseqaij) {
799704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
799804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
799904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
800004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
800104708bb6SStefano Zampini       } else {
8002511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
800304708bb6SStefano Zampini       }
800404708bb6SStefano Zampini     }
8005a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8006a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8007ca92afb2SStefano Zampini     } else {
8008a3df083aSStefano Zampini       benign_n = 0;
8009ca92afb2SStefano Zampini     }
8010b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8011b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8012b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
801372b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
801422db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8015b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
801622db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8017b7ab4a40SStefano Zampini     }
8018b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8019b7ab4a40SStefano 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 */
8020b7ab4a40SStefano Zampini     if (need_change) {
802188c03ad3SStefano Zampini       PC_IS   *pcisf;
802288c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
802388c03ad3SStefano Zampini       PC      pcf;
802488c03ad3SStefano Zampini 
8025e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
802688c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
802788c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
802888c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
802988c03ad3SStefano Zampini       /* hacks */
803088c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
803172b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
803272b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
803372b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
803472b8c272SStefano Zampini       pcisf->n = pcis->n;
803572b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
803688c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
803788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
803888c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
803988c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
804088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
804188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
804272b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
804388c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
804488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
804572b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
804672b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
804772b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
804872b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
804972b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
805088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
805172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
805288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
805388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
805488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
805588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
805688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
805788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
805888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
805988c03ad3SStefano Zampini     }
80609d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
806191af6908SStefano 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);
806272b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
806372b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8064ca92afb2SStefano Zampini   }
8065d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8066b96c3477SStefano Zampini 
8067b96c3477SStefano Zampini   /* free adjacency */
8068b96c3477SStefano Zampini   if (free_used_adj) {
8069b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8070b96c3477SStefano Zampini   }
8071b96c3477SStefano Zampini   PetscFunctionReturn(0);
8072b96c3477SStefano Zampini }
8073b96c3477SStefano Zampini 
8074b96c3477SStefano Zampini #undef __FUNCT__
8075b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
807608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8077b96c3477SStefano Zampini {
8078b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8079b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8080b96c3477SStefano Zampini   PCBDDCGraph         graph;
8081b96c3477SStefano Zampini   PetscErrorCode      ierr;
8082b96c3477SStefano Zampini 
8083b96c3477SStefano Zampini   PetscFunctionBegin;
8084b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
808508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
80863301b35fSStefano Zampini     IS       verticesIS,verticescomm;
80873301b35fSStefano Zampini     PetscInt vsize,*idxs;
8088b96c3477SStefano Zampini 
8089b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
80903301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
80913301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
80923301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
80933301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8094c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8095b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8096be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8097441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
80983301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8099b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8100b96c3477SStefano Zampini   } else {
8101b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8102b96c3477SStefano Zampini   }
8103e4d548c7SStefano Zampini   /* print some info */
81045c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8105e4d548c7SStefano Zampini     IS       vertices;
8106e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8107c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8108e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8109e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8110e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8111e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8112e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8113e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8114e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8115e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8116e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8117c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8118e4d548c7SStefano Zampini   }
8119b96c3477SStefano Zampini 
8120b96c3477SStefano Zampini   /* sub_schurs init */
8121b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8122b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8123b334f244SStefano Zampini   }
81248b6046baSStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
8125a64f4aa4SStefano Zampini 
8126b96c3477SStefano Zampini   /* free graph struct */
812708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8128b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8129b96c3477SStefano Zampini   }
8130b96c3477SStefano Zampini   PetscFunctionReturn(0);
8131b96c3477SStefano Zampini }
8132fa34dd3eSStefano Zampini 
8133fa34dd3eSStefano Zampini #undef __FUNCT__
8134fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
8135fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8136fa34dd3eSStefano Zampini {
8137fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8138fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8139fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8140fa34dd3eSStefano Zampini 
8141fa34dd3eSStefano Zampini   PetscFunctionBegin;
8142fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8143fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
81444f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8145fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
81464f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
814775c01103SStefano Zampini     PetscReal      norm;
8148fa34dd3eSStefano Zampini     PetscInt       i;
8149fa34dd3eSStefano Zampini 
8150fa34dd3eSStefano Zampini     /* B0 and B0_B */
8151fa34dd3eSStefano Zampini     if (zerodiag) {
8152fa34dd3eSStefano Zampini       IS       dummy;
8153fa34dd3eSStefano Zampini 
81544f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
81554f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8156fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8157fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8158fa34dd3eSStefano Zampini     }
8159fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8160fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8161fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8162fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8163fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8164fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8165fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8166fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8167fa34dd3eSStefano Zampini     /* S_j */
8168fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8169fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8170fa34dd3eSStefano Zampini 
8171fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8172fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8173fa34dd3eSStefano Zampini     /* continuous in primal space */
8174fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8175fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8176fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8177fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
81784f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
81794f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8180fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8181fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8182fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8183fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8184fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8185fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8186fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8187fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8188fa34dd3eSStefano Zampini 
8189fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8190fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8191fa34dd3eSStefano Zampini     /* local with Schur */
8192fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8193fa34dd3eSStefano Zampini     if (zerodiag) {
8194fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
81954f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8196fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8197fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8198fa34dd3eSStefano Zampini     }
8199fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8200fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8201fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8202fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8203fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8204fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8205fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8206fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8207fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8208fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8209fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8210fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8211fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8212fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8213fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8214fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8215fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8216fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8217fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8218fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8219fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8220fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8221fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8222fa34dd3eSStefano Zampini     if (zerodiag) {
8223fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8224fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
82254f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8226fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8227fa34dd3eSStefano Zampini     }
8228fa34dd3eSStefano Zampini     /* BDDC */
8229fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8230fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8231fa34dd3eSStefano Zampini 
8232fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8233fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8234fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8235fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
82364f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
82374f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8238fa34dd3eSStefano Zampini     }
82394f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8240fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8241fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8242fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8243fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8244fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8245fa34dd3eSStefano Zampini   }
8246fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8247fa34dd3eSStefano Zampini }
82481e0482f5SStefano Zampini 
82491e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
82501e0482f5SStefano Zampini #undef __FUNCT__
82511e0482f5SStefano Zampini #define __FUNCT__ "MatMPIAIJRestrict"
82521e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
82531e0482f5SStefano Zampini {
82541e0482f5SStefano Zampini   Mat            At;
82551e0482f5SStefano Zampini   IS             rows;
82561e0482f5SStefano Zampini   PetscInt       rst,ren;
82571e0482f5SStefano Zampini   PetscErrorCode ierr;
82581e0482f5SStefano Zampini   PetscLayout    rmap;
82591e0482f5SStefano Zampini 
82601e0482f5SStefano Zampini   PetscFunctionBegin;
82611e0482f5SStefano Zampini   rst = ren = 0;
82621e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
82631e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
82641e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
82651e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
82661e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
82671e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
82681e0482f5SStefano Zampini   }
8269e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
82701e0482f5SStefano Zampini   ierr = MatGetSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
82711e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
82721e0482f5SStefano Zampini 
82731e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
82741e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
82751e0482f5SStefano Zampini     IS         from,to;
82761e0482f5SStefano Zampini     Vec        gvec;
82771e0482f5SStefano Zampini     PetscInt   lsize;
82781e0482f5SStefano Zampini 
82791e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
82801e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
82811e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
82821e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
82831e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
82841e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
82851e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
82861e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
82871e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
82881e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
82891e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
82901e0482f5SStefano Zampini     b->A = a->A;
82911e0482f5SStefano Zampini     b->B = a->B;
82921e0482f5SStefano Zampini 
82931e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
82941e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
82951e0482f5SStefano Zampini     b->rowindices      = 0;
82961e0482f5SStefano Zampini     b->rowvalues       = 0;
82971e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
82981e0482f5SStefano Zampini 
82991e0482f5SStefano Zampini     (*B)->rmap         = rmap;
83001e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
83011e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
83021e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
83031e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
83041e0482f5SStefano Zampini 
83051e0482f5SStefano Zampini     if (a->colmap) {
83061e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
83071e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
83081e0482f5SStefano Zampini #else
83091e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
83101e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
83111e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
83121e0482f5SStefano Zampini #endif
83131e0482f5SStefano Zampini     } else b->colmap = 0;
83141e0482f5SStefano Zampini     if (a->garray) {
83151e0482f5SStefano Zampini       PetscInt len;
83161e0482f5SStefano Zampini       len  = a->B->cmap->n;
83171e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
83181e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
83191e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
83201e0482f5SStefano Zampini     } else b->garray = 0;
83211e0482f5SStefano Zampini 
83221e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
83231e0482f5SStefano Zampini     b->lvec = a->lvec;
83241e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
83251e0482f5SStefano Zampini 
83261e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
83271e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
83281e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
83291e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
83301e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
83311e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
83321e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
83331e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
83341e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
83351e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
83361e0482f5SStefano Zampini   }
83371e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
83381e0482f5SStefano Zampini   PetscFunctionReturn(0);
83391e0482f5SStefano Zampini }
8340