xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 614dbb09543bd50f1f5acf163f8f28ef405c39f9)
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 
9f498cd09SStefano Zampini /* if range is true,  it returns B s.t. span{B} = range(A)
10f498cd09SStefano Zampini    if range is false, it returns B s.t. range(B) _|_ range(A) */
11a13144ffSStefano Zampini #undef __FUNCT__
12f498cd09SStefano Zampini #define __FUNCT__ "MatDenseOrthogonalRangeOrComplement"
13f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
14a13144ffSStefano Zampini {
15a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
16a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
17a13144ffSStefano Zampini   PetscReal      *sing;
18a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
19a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
20a13144ffSStefano Zampini   PetscErrorCode ierr;
21a13144ffSStefano Zampini 
22a13144ffSStefano Zampini   PetscFunctionBegin;
23a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
24a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
25*614dbb09SStefano Zampini #else
26a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
27a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
28a13144ffSStefano Zampini 
29a13144ffSStefano Zampini   /* workspace */
30a13144ffSStefano Zampini   if (!work) {
31a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
32f913dca9SStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);CHKERRQ(ierr);
33a13144ffSStefano Zampini   } else {
34a13144ffSStefano Zampini     ulw   = lw;
35a13144ffSStefano Zampini     uwork = work;
36a13144ffSStefano Zampini   }
37a13144ffSStefano Zampini   n = PetscMin(nr,nc);
38a13144ffSStefano Zampini   if (!rwork) {
39a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
40a13144ffSStefano Zampini   } else {
41a13144ffSStefano Zampini     sing = rwork;
42a13144ffSStefano Zampini   }
43a13144ffSStefano Zampini 
44a13144ffSStefano Zampini   /* SVD */
45a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
46a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
47a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
48a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
49a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
50a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
51a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
52a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
53a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
54a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
55a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
56a13144ffSStefano Zampini   if (!rwork) {
57a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
58a13144ffSStefano Zampini   }
59a13144ffSStefano Zampini   if (!work) {
60a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
61a13144ffSStefano Zampini   }
62a13144ffSStefano Zampini   /* create B */
63f498cd09SStefano Zampini   if (!range) {
64a13144ffSStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
65a13144ffSStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
66a13144ffSStefano Zampini     ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
67f498cd09SStefano Zampini   } else {
68f498cd09SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B);CHKERRQ(ierr);
69f498cd09SStefano Zampini     ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
70f498cd09SStefano Zampini     ierr = PetscMemcpy(data,U,i*nr*sizeof(PetscScalar));CHKERRQ(ierr);
71f498cd09SStefano Zampini   }
72a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
73a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
74*614dbb09SStefano Zampini #endif
75*614dbb09SStefano Zampini #else /* PETSC_USE_COMPLEX */
76a13144ffSStefano Zampini   PetscFunctionBegin;
77a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
78a13144ffSStefano Zampini #endif
79a13144ffSStefano Zampini   PetscFunctionReturn(0);
80a13144ffSStefano Zampini }
81a13144ffSStefano Zampini 
821e0482f5SStefano Zampini /* TODO REMOVE */
831e0482f5SStefano Zampini #if defined(PRINT_GDET)
841e0482f5SStefano Zampini static int inc = 0;
851e0482f5SStefano Zampini static int lev = 0;
861e0482f5SStefano Zampini #endif
871e0482f5SStefano Zampini 
88a13144ffSStefano Zampini #undef __FUNCT__
89a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCComputeNedelecChangeEdge"
901e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork)
91a13144ffSStefano Zampini {
92a13144ffSStefano Zampini   PetscErrorCode ierr;
93a13144ffSStefano Zampini   Mat            GE,GEd;
94a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
95a13144ffSStefano Zampini   PetscScalar    *ptr;
96a13144ffSStefano Zampini 
97a13144ffSStefano Zampini   PetscFunctionBegin;
98a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
99c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
100a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
102a13144ffSStefano Zampini 
103a13144ffSStefano Zampini   /* gradients */
104a13144ffSStefano Zampini   ptr  = work + 5*esize;
105a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
106a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
107a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
108a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
109a13144ffSStefano Zampini 
110a13144ffSStefano Zampini   /* constants */
111a13144ffSStefano Zampini   ptr += rsize*csize;
112a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
113a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
114a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
115a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
116f498cd09SStefano Zampini   ierr = MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins);CHKERRQ(ierr);
117a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1181e0482f5SStefano Zampini 
1191e0482f5SStefano Zampini   if (corners) {
1201e0482f5SStefano Zampini     Mat            GEc;
1211e0482f5SStefano Zampini     PetscScalar    *vals,v;
1221e0482f5SStefano Zampini 
1231e0482f5SStefano Zampini     ierr = MatGetSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc);CHKERRQ(ierr);
1241e0482f5SStefano Zampini     ierr = MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd);CHKERRQ(ierr);
1251e0482f5SStefano Zampini     ierr = MatDenseGetArray(GEd,&vals);CHKERRQ(ierr);
126637e8532SStefano Zampini     /* v    = PetscAbsScalar(vals[0]) */;
127637e8532SStefano Zampini     v    = 1.;
1281e0482f5SStefano Zampini     cvals[0] = vals[0]/v;
1291e0482f5SStefano Zampini     cvals[1] = vals[1]/v;
1301e0482f5SStefano Zampini     ierr = MatDenseRestoreArray(GEd,&vals);CHKERRQ(ierr);
1311e0482f5SStefano Zampini     ierr = MatScale(*GKins,1./v);CHKERRQ(ierr);
1321e0482f5SStefano Zampini #if defined(PRINT_GDET)
1331e0482f5SStefano Zampini     {
1341e0482f5SStefano Zampini       PetscViewer viewer;
1351e0482f5SStefano Zampini       char filename[256];
1361e0482f5SStefano Zampini       sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++);
1371e0482f5SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1381e0482f5SStefano Zampini       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1391e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEc,"GEc");CHKERRQ(ierr);
1401e0482f5SStefano Zampini       ierr = MatView(GEc,viewer);CHKERRQ(ierr);
1411e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)(*GKins),"GK");CHKERRQ(ierr);
1421e0482f5SStefano Zampini       ierr = MatView(*GKins,viewer);CHKERRQ(ierr);
1431e0482f5SStefano Zampini       ierr = PetscObjectSetName((PetscObject)GEd,"Gproj");CHKERRQ(ierr);
1441e0482f5SStefano Zampini       ierr = MatView(GEd,viewer);CHKERRQ(ierr);
1451e0482f5SStefano Zampini       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1461e0482f5SStefano Zampini     }
1471e0482f5SStefano Zampini #endif
1481e0482f5SStefano Zampini     ierr = MatDestroy(&GEd);CHKERRQ(ierr);
1491e0482f5SStefano Zampini     ierr = MatDestroy(&GEc);CHKERRQ(ierr);
1501e0482f5SStefano Zampini   }
1511e0482f5SStefano Zampini 
152a13144ffSStefano Zampini   PetscFunctionReturn(0);
153a13144ffSStefano Zampini }
154a13144ffSStefano Zampini 
155a13144ffSStefano Zampini #undef __FUNCT__
156a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCNedelecSupport"
157a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
158a13144ffSStefano Zampini {
159a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
160a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1610569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
162eee23b56SStefano Zampini   Vec                    tvec;
163a13144ffSStefano Zampini   PetscSF                sfv;
1641e0482f5SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g;
165a13144ffSStefano Zampini   MPI_Comm               comm;
166c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
167c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
1687d871cd7SStefano Zampini   PetscBT                btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter;
169a13144ffSStefano Zampini   PetscScalar            *vals,*work;
170a13144ffSStefano Zampini   PetscReal              *rwork;
171a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
1721e0482f5SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
173a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
174eee23b56SStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,nee;
175b03ebc13SStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*vmarks,*gidxs;
176a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
177b03ebc13SStefano Zampini   PetscInt               *corners,*cedges;
178637e8532SStefano Zampini   PetscInt               *ecount,**eneighs,*vcount,**vneighs;
179b03ebc13SStefano Zampini #if defined(PETSC_USE_DEBUG)
180b03ebc13SStefano Zampini   PetscInt               *emarks;
181b03ebc13SStefano Zampini #endif
1821e0482f5SStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,global;
183a13144ffSStefano Zampini   PetscErrorCode         ierr;
184a13144ffSStefano Zampini 
185a13144ffSStefano Zampini   PetscFunctionBegin;
186a13144ffSStefano Zampini   /* test variable order code and print debug info TODO: to be removed */
187a13144ffSStefano Zampini   print = PETSC_FALSE;
188a13144ffSStefano Zampini   ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_print_nedelec",&print,NULL);CHKERRQ(ierr);
189a13144ffSStefano Zampini   ierr = PetscOptionsGetInt(NULL,NULL,"-pc_bddc_nedelec_order",&pcbddc->nedorder,NULL);CHKERRQ(ierr);
190a13144ffSStefano Zampini 
191a13144ffSStefano Zampini   /* Return to caller if there are no edges in the decomposition */
192a13144ffSStefano Zampini   ierr   = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1931e0482f5SStefano Zampini   ierr   = MatGetLocalToGlobalMapping(pc->pmat,&al2g,NULL);CHKERRQ(ierr);
1941e0482f5SStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(al2g,&n);CHKERRQ(ierr);
195a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
196a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
197c2151214SStefano Zampini   for (i=0;i<n;i++) {
198a13144ffSStefano Zampini     if (PetscRealPart(vals[i]) > 2.) {
199a13144ffSStefano Zampini       lrc[0] = PETSC_TRUE;
200a13144ffSStefano Zampini       break;
201a13144ffSStefano Zampini     }
202a13144ffSStefano Zampini   }
203a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
204a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
205a13144ffSStefano Zampini   if (!lrc[1]) PetscFunctionReturn(0);
206a13144ffSStefano Zampini 
2071e0482f5SStefano Zampini   /* If the discrete gradient is defined for a subset of dofs and global is true,
2081e0482f5SStefano Zampini      it assumes G is given in global ordering for all the dofs.
2091e0482f5SStefano Zampini      Otherwise, the ordering is global for the Nedelec field */
210a13144ffSStefano Zampini   order      = pcbddc->nedorder;
211a13144ffSStefano Zampini   conforming = pcbddc->conforming;
212c2151214SStefano Zampini   field      = pcbddc->nedfield;
2131e0482f5SStefano Zampini   global     = pcbddc->nedglobal;
214c2151214SStefano 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);
215c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field > -1) {
2161e0482f5SStefano Zampini     PetscBool setprimal = PETSC_FALSE;
2171e0482f5SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field_primal",&setprimal,NULL);CHKERRQ(ierr);
218c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
219c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
220c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
2211e0482f5SStefano Zampini     if (setprimal) {
222eee23b56SStefano Zampini       IS       enedfieldlocal;
223eee23b56SStefano Zampini       PetscInt *eidxs;
224eee23b56SStefano Zampini 
225eee23b56SStefano Zampini       ierr = PetscMalloc1(ne,&eidxs);CHKERRQ(ierr);
226eee23b56SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
227eee23b56SStefano Zampini       ierr = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
228eee23b56SStefano Zampini       for (i=0,cum=0;i<ne;i++) {
229eee23b56SStefano Zampini         if (PetscRealPart(vals[idxs[i]]) > 2.) {
230eee23b56SStefano Zampini           eidxs[cum++] = idxs[i];
231eee23b56SStefano Zampini         }
232eee23b56SStefano Zampini       }
233eee23b56SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
234eee23b56SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
235eee23b56SStefano Zampini       ierr = ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal);CHKERRQ(ierr);
236eee23b56SStefano Zampini       ierr = PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal);CHKERRQ(ierr);
237eee23b56SStefano Zampini       ierr = PetscFree(eidxs);CHKERRQ(ierr);
2381e0482f5SStefano Zampini       ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
239eee23b56SStefano Zampini       ierr = ISDestroy(&enedfieldlocal);CHKERRQ(ierr);
2401e0482f5SStefano Zampini       PetscFunctionReturn(0);
2411e0482f5SStefano Zampini     }
2421e0482f5SStefano Zampini   } else if (!pcbddc->n_ISForDofsLocal) {
243c2151214SStefano Zampini     PetscBool testnedfield = PETSC_FALSE;
244c2151214SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field",&testnedfield,NULL);CHKERRQ(ierr);
245c2151214SStefano Zampini     if (!testnedfield) {
246c2151214SStefano Zampini       ne            = n;
247c2151214SStefano Zampini       nedfieldlocal = NULL;
248c2151214SStefano Zampini     } else {
249c2151214SStefano Zampini       /* ierr = ISCreateStride(comm,n,0,1,&nedfieldlocal);CHKERRQ(ierr); */
250c2151214SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
251c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
252c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
253c2151214SStefano Zampini       for (i=0;i<n;i++) matis->sf_leafdata[i] = 1;
254c2151214SStefano Zampini       ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
255c2151214SStefano Zampini       ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
256c2151214SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
257c2151214SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
258c2151214SStefano Zampini       for (i=0,cum=0;i<n;i++) {
259c2151214SStefano Zampini         if (matis->sf_leafdata[i] > 1) {
260c2151214SStefano Zampini           matis->sf_leafdata[cum++] = i;
261c2151214SStefano Zampini         }
262c2151214SStefano Zampini       }
263c2151214SStefano Zampini       ierr = ISCreateGeneral(comm,cum,matis->sf_leafdata,PETSC_COPY_VALUES,&nedfieldlocal);CHKERRQ(ierr);
264c2151214SStefano Zampini       ierr = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
265c2151214SStefano Zampini     }
2661e0482f5SStefano Zampini     global = PETSC_TRUE;
2671e0482f5SStefano Zampini   } else {
2681e0482f5SStefano Zampini     SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified");
269c2151214SStefano Zampini   }
270a13144ffSStefano Zampini 
271c2151214SStefano Zampini   if (nedfieldlocal) { /* merge with previous code when testing is done */
272c2151214SStefano Zampini     IS is;
273c2151214SStefano Zampini 
274c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
275c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
2761e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering for the whole dofs*/
2771e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is);CHKERRQ(ierr);
2781e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&al2g);CHKERRQ(ierr);
2791e0482f5SStefano Zampini     /* need to map from the local Nedelec field to global numbering (for Nedelec only) */
2801e0482f5SStefano Zampini     if (global) {
2811e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2821e0482f5SStefano Zampini       el2g = al2g;
2831e0482f5SStefano Zampini     } else {
2841e0482f5SStefano Zampini       IS gis;
2851e0482f5SStefano Zampini 
2861e0482f5SStefano Zampini       ierr = ISRenumber(is,NULL,NULL,&gis);CHKERRQ(ierr);
2871e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(gis,&el2g);CHKERRQ(ierr);
2881e0482f5SStefano Zampini       ierr = ISDestroy(&gis);CHKERRQ(ierr);
2891e0482f5SStefano Zampini     }
290c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
291c2151214SStefano Zampini   } else {
2921e0482f5SStefano Zampini     /* restore default */
2931e0482f5SStefano Zampini     pcbddc->nedfield = -1;
2941e0482f5SStefano Zampini     /* one ref for the destruction of al2g, one for el2g */
2951e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2961e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)al2g);CHKERRQ(ierr);
2971e0482f5SStefano Zampini     el2g = al2g;
298c2151214SStefano Zampini     fl2g = NULL;
299c2151214SStefano Zampini   }
300a13144ffSStefano Zampini 
301a13144ffSStefano Zampini   /* Sanity checks */
302a13144ffSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
303a13144ffSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
304a13144ffSStefano 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);
305a13144ffSStefano Zampini 
3061e0482f5SStefano Zampini   /* Drop connections for interior edges */
3071e0482f5SStefano Zampini   ierr = MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G);CHKERRQ(ierr);
3081e0482f5SStefano Zampini   ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
309c2151214SStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
310c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
311c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
312c2151214SStefano Zampini   if (nedfieldlocal) {
313c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
314c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
315c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
316c2151214SStefano Zampini   } else {
317c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
318c2151214SStefano Zampini   }
319c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
320c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
3211e0482f5SStefano Zampini   if (global) {
3221e0482f5SStefano Zampini     PetscInt rst;
3231e0482f5SStefano Zampini 
324c2151214SStefano Zampini     ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
325c2151214SStefano Zampini     for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
326c2151214SStefano Zampini       if (matis->sf_rootdata[i] < 2) {
327c2151214SStefano Zampini         matis->sf_rootdata[cum++] = i + rst;
328c2151214SStefano Zampini       }
329c2151214SStefano Zampini     }
330a13144ffSStefano Zampini     ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
331c2151214SStefano Zampini     ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
3321e0482f5SStefano Zampini   } else {
3331e0482f5SStefano Zampini     PetscInt *tbz;
3341e0482f5SStefano Zampini 
3351e0482f5SStefano Zampini     ierr = PetscMalloc1(ne,&tbz);CHKERRQ(ierr);
3361e0482f5SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3371e0482f5SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
3381e0482f5SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3391e0482f5SStefano Zampini     for (i=0,cum=0;i<ne;i++)
3401e0482f5SStefano Zampini       if (matis->sf_leafdata[idxs[i]] == 1)
3411e0482f5SStefano Zampini         tbz[cum++] = i;
3421e0482f5SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
3431e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz);CHKERRQ(ierr);
3441e0482f5SStefano Zampini     ierr = MatZeroRows(G,cum,tbz,0.,NULL,NULL);CHKERRQ(ierr);
3451e0482f5SStefano Zampini     ierr = PetscFree(tbz);CHKERRQ(ierr);
3461e0482f5SStefano Zampini   }
347a13144ffSStefano Zampini 
348a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
349a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
350a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
351a13144ffSStefano Zampini   ierr = MatGetSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
352a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
353a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
354a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
355a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
356a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
357a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
358a13144ffSStefano Zampini   if (print) {
359a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
360a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
361a13144ffSStefano Zampini   }
362a13144ffSStefano Zampini 
363a13144ffSStefano Zampini   /* SF for nodal communications */
364c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
365a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
366a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
367a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
368a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
369a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
370a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
371a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
372a13144ffSStefano Zampini   ierr = PetscMalloc2(nv,&sfvleaves,Lv,&sfvroots);CHKERRQ(ierr);
373a13144ffSStefano Zampini 
3741e0482f5SStefano Zampini   /* Destroy temporary G created in MATIS format and modified G */
3751e0482f5SStefano Zampini   ierr = MatDestroy(&G);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
377a13144ffSStefano Zampini 
3780569b399SStefano Zampini   /* Save lG */
3790569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
3800569b399SStefano Zampini 
381a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
3824e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
3834e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
3877d871cd7SStefano Zampini   ierr = PetscBTCreate(ne,&btbd);CHKERRQ(ierr);
388c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
389a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
390a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
391a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
392c2151214SStefano Zampini     IS is;
393c2151214SStefano Zampini 
394c2151214SStefano Zampini     if (fl2g) {
395c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
396c2151214SStefano Zampini     } else {
397c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
398c2151214SStefano Zampini     }
399c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
400c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
401a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
402a13144ffSStefano Zampini       if (idxs[i] >= 0) {
403a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
4047d871cd7SStefano Zampini         ierr = PetscBTSet(btbd,idxs[i]);CHKERRQ(ierr);
405a13144ffSStefano Zampini       }
406a13144ffSStefano Zampini     }
407c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
408c2151214SStefano Zampini     if (fl2g) {
409c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
410c2151214SStefano Zampini     }
411a13144ffSStefano Zampini   }
412a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
413c2151214SStefano Zampini     IS is;
414c2151214SStefano Zampini 
415c2151214SStefano Zampini     if (fl2g) {
416c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
417c2151214SStefano Zampini     } else {
418c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
419c2151214SStefano Zampini     }
420c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
421c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
422a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
423a13144ffSStefano Zampini       if (idxs[i] >= 0) {
424a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
425a13144ffSStefano Zampini       }
426a13144ffSStefano Zampini     }
427c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
428c2151214SStefano Zampini     if (fl2g) {
429c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
430a13144ffSStefano Zampini     }
431c2151214SStefano Zampini   }
432c2151214SStefano Zampini 
433637e8532SStefano Zampini   /* count neighs per dof */
434637e8532SStefano Zampini   ierr = PetscCalloc1(ne,&ecount);CHKERRQ(ierr);
435637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&eneighs);CHKERRQ(ierr);
436637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
437637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
438637e8532SStefano Zampini     cum += n_shared[i];
439637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
440637e8532SStefano Zampini       ecount[shared[i][j]]++;
441637e8532SStefano Zampini     }
442637e8532SStefano Zampini   }
443637e8532SStefano Zampini   if (ne) {
444637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&eneighs[0]);CHKERRQ(ierr);
445637e8532SStefano Zampini   }
446637e8532SStefano Zampini   for (i=1;i<ne;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
447637e8532SStefano Zampini   ierr = PetscMemzero(ecount,ne*sizeof(PetscInt));CHKERRQ(ierr);
448637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
449637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
450637e8532SStefano Zampini       PetscInt k = shared[i][j];
451637e8532SStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
452637e8532SStefano Zampini       ecount[k]++;
453637e8532SStefano Zampini     }
454637e8532SStefano Zampini   }
455637e8532SStefano Zampini   for (i=0;i<ne;i++) {
456637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr);
457637e8532SStefano Zampini   }
458637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
459637e8532SStefano Zampini   ierr = PetscCalloc1(nv,&vcount);CHKERRQ(ierr);
460637e8532SStefano Zampini   ierr = PetscMalloc1(nv,&vneighs);CHKERRQ(ierr);
461637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
462637e8532SStefano Zampini   for (i=1,cum=0;i<n_neigh;i++) {
463637e8532SStefano Zampini     cum += n_shared[i];
464637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
465637e8532SStefano Zampini       vcount[shared[i][j]]++;
466637e8532SStefano Zampini     }
467637e8532SStefano Zampini   }
468637e8532SStefano Zampini   if (nv) {
469637e8532SStefano Zampini     ierr = PetscMalloc1(cum,&vneighs[0]);CHKERRQ(ierr);
470637e8532SStefano Zampini   }
471637e8532SStefano Zampini   for (i=1;i<nv;i++) vneighs[i] = vneighs[i-1] + vcount[i-1];
472637e8532SStefano Zampini   ierr = PetscMemzero(vcount,nv*sizeof(PetscInt));CHKERRQ(ierr);
473637e8532SStefano Zampini   for (i=1;i<n_neigh;i++) {
474637e8532SStefano Zampini     for (j=0;j<n_shared[i];j++) {
475637e8532SStefano Zampini       PetscInt k = shared[i][j];
476637e8532SStefano Zampini       vneighs[k][vcount[k]] = neigh[i];
477637e8532SStefano Zampini       vcount[k]++;
478637e8532SStefano Zampini     }
479637e8532SStefano Zampini   }
480637e8532SStefano Zampini   for (i=0;i<nv;i++) {
481637e8532SStefano Zampini     ierr = PetscSortRemoveDupsInt(&vcount[i],vneighs[i]);CHKERRQ(ierr);
482637e8532SStefano Zampini   }
483637e8532SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
484637e8532SStefano Zampini 
4857d871cd7SStefano Zampini   /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs
4867d871cd7SStefano Zampini      for proper detection of coarse edges' endpoints */
48762b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
48862b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
4897d871cd7SStefano Zampini     if ((ecount[i] > 1 && !PetscBTLookup(btbd,i)) || (ecount[i] == 1 && PetscBTLookup(btb,i))) {
49062b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
49162b0c6f7SStefano Zampini     }
49262b0c6f7SStefano Zampini   }
493637e8532SStefano Zampini   ierr = PetscMalloc1(ne,&marks);CHKERRQ(ierr);
49462b0c6f7SStefano Zampini   if (!conforming) {
49562b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
49662b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
49762b0c6f7SStefano Zampini   }
4984e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
499dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
50062b0c6f7SStefano Zampini   cum  = 0;
501a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
502dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
50362b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
504a13144ffSStefano Zampini       marks[cum++] = i;
505dec27d64SStefano Zampini       continue;
506dec27d64SStefano Zampini     }
507dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
50862b0c6f7SStefano Zampini     if (!conforming) {
50962b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
510a13144ffSStefano Zampini         marks[cum++] = i;
511a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
512a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
513a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
514a13144ffSStefano Zampini         }
51562b0c6f7SStefano Zampini       } else {
51662b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
51762b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
51862b0c6f7SStefano Zampini            - at most 2 endpoints
51962b0c6f7SStefano Zampini            - order-1 interior nodal dofs
52062b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
52162b0c6f7SStefano Zampini         */
52262b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
52362b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
52462b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
52562b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
52662b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
52762b0c6f7SStefano Zampini           if (nconn > order) ends++;
52862b0c6f7SStefano Zampini           else if (nconn == order) ints++;
52962b0c6f7SStefano Zampini           else undef++;
53062b0c6f7SStefano Zampini         }
53162b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
53262b0c6f7SStefano Zampini           marks[cum++] = i;
53362b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
53462b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
53562b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
53662b0c6f7SStefano Zampini           }
53762b0c6f7SStefano Zampini         }
53862b0c6f7SStefano Zampini       }
539a13144ffSStefano Zampini     }
540dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
541dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
542dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
543dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
544a13144ffSStefano Zampini     }
545dec27d64SStefano Zampini   }
54662b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
547dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
5484e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
54962b0c6f7SStefano Zampini   if (!conforming) {
55062b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
55162b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
55262b0c6f7SStefano Zampini   }
5534e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
554637e8532SStefano Zampini 
555b03ebc13SStefano Zampini   /* identify splitpoints and corner candidates */
5564e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
557a13144ffSStefano Zampini   if (print) {
5584e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
5594e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
5604e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
561a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
562a13144ffSStefano Zampini   }
563a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
564dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
565a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
566637e8532SStefano Zampini     PetscInt  ord = order, test = ii[i+1]-ii[i], vc = vcount[i];
5677d871cd7SStefano Zampini     PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE;
568b03ebc13SStefano Zampini     if (!order) { /* variable order */
569dec27d64SStefano Zampini       PetscReal vorder = 0.;
570dec27d64SStefano Zampini 
571dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
572dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
573dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
574dec27d64SStefano Zampini       ord  = 1;
575dec27d64SStefano Zampini     }
576a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
577dec27d64SStefano 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);
578a13144ffSStefano Zampini #endif
579637e8532SStefano Zampini     for (j=ii[i];j<ii[i+1] && sneighs;j++) {
5807d871cd7SStefano Zampini       if (PetscBTLookup(btbd,jj[j])) {
5817d871cd7SStefano Zampini         bdir = PETSC_TRUE;
5827d871cd7SStefano Zampini         break;
5837d871cd7SStefano Zampini       }
584637e8532SStefano Zampini       if (vc != ecount[jj[j]]) {
585637e8532SStefano Zampini         sneighs = PETSC_FALSE;
586637e8532SStefano Zampini       } else {
587637e8532SStefano Zampini         PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]];
588637e8532SStefano Zampini         for (k=0;k<vc;k++) {
589637e8532SStefano Zampini           if (vn[k] != en[k]) {
590637e8532SStefano Zampini             sneighs = PETSC_FALSE;
591637e8532SStefano Zampini             break;
592637e8532SStefano Zampini           }
593637e8532SStefano Zampini         }
594637e8532SStefano Zampini       }
595637e8532SStefano Zampini     }
5967d871cd7SStefano Zampini     if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */
5977d871cd7SStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d (%d %d %d)\n",i,!sneighs,test >= 3*ord,bdir);
598a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
599dec27d64SStefano Zampini     } else if (test == ord) {
600b03ebc13SStefano Zampini       if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) {
601a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
602a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
603a13144ffSStefano Zampini       } else {
604a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
605a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
606a13144ffSStefano Zampini       }
607a13144ffSStefano Zampini     }
608a13144ffSStefano Zampini   }
609637e8532SStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
610637e8532SStefano Zampini   ierr = PetscFree(vcount);CHKERRQ(ierr);
611637e8532SStefano Zampini   if (ne) {
612637e8532SStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
613637e8532SStefano Zampini   }
614637e8532SStefano Zampini   if (nv) {
615637e8532SStefano Zampini     ierr = PetscFree(vneighs[0]);CHKERRQ(ierr);
616637e8532SStefano Zampini   }
617637e8532SStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
618637e8532SStefano Zampini   ierr = PetscFree(vneighs);CHKERRQ(ierr);
6197d871cd7SStefano Zampini   ierr = PetscBTDestroy(&btbd);CHKERRQ(ierr);
620b03ebc13SStefano Zampini 
621b03ebc13SStefano Zampini   /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */
622b03ebc13SStefano Zampini   if (order != 1) {
623b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n");
624b03ebc13SStefano Zampini     ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
625b03ebc13SStefano Zampini     for (i=0;i<nv;i++) {
626b03ebc13SStefano Zampini       if (PetscBTLookup(btvcand,i)) {
627b03ebc13SStefano Zampini         PetscBool found = PETSC_FALSE;
628b03ebc13SStefano Zampini         for (j=ii[i];j<ii[i+1] && !found;j++) {
629b03ebc13SStefano Zampini           PetscInt k,e = jj[j];
630b03ebc13SStefano Zampini           if (PetscBTLookup(bte,e)) continue;
631b03ebc13SStefano Zampini           for (k=iit[e];k<iit[e+1];k++) {
632b03ebc13SStefano Zampini             PetscInt v = jjt[k];
633b03ebc13SStefano Zampini             if (v != i && PetscBTLookup(btvcand,v)) {
634b03ebc13SStefano Zampini               found = PETSC_TRUE;
635b03ebc13SStefano Zampini               break;
636b03ebc13SStefano Zampini             }
637b03ebc13SStefano Zampini           }
638b03ebc13SStefano Zampini         }
639b03ebc13SStefano Zampini         if (!found) {
640b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d CLEARED\n",i);
641b03ebc13SStefano Zampini           ierr = PetscBTClear(btvcand,i);CHKERRQ(ierr);
642b03ebc13SStefano Zampini         } else {
643b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  CANDIDATE %d ACCEPTED\n",i);
644b03ebc13SStefano Zampini         }
645b03ebc13SStefano Zampini       }
646b03ebc13SStefano Zampini     }
647b03ebc13SStefano Zampini     ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
648b03ebc13SStefano Zampini   }
649dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
650a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
651b03ebc13SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
652a13144ffSStefano Zampini 
653a13144ffSStefano Zampini   /* Get the local G^T explicitly */
6540569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
655a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6564e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
657a13144ffSStefano Zampini 
6584e64d54eSstefano_zampini   /* Mark interior nodal dofs */
659a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
6604e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
661a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
662a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
6634e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
664a13144ffSStefano Zampini     }
665a13144ffSStefano Zampini   }
666a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
667a13144ffSStefano Zampini 
668a13144ffSStefano Zampini   /* communicate corners and splitpoints */
669a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
670a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
671a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
672a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
673a13144ffSStefano Zampini 
674a13144ffSStefano Zampini   if (print) {
675a13144ffSStefano Zampini     IS tbz;
676a13144ffSStefano Zampini 
677a13144ffSStefano Zampini     cum = 0;
678a13144ffSStefano Zampini     for (i=0;i<nv;i++)
679a13144ffSStefano Zampini       if (sfvleaves[i])
680a13144ffSStefano Zampini         vmarks[cum++] = i;
681a13144ffSStefano Zampini 
682a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
683a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
684a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
685a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
686a13144ffSStefano Zampini   }
687a13144ffSStefano Zampini 
688a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
689a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
690a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
691a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
692a13144ffSStefano Zampini 
6934e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
6944e64d54eSstefano_zampini      and interior nodal dofs */
695a13144ffSStefano Zampini   cum = 0;
696a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
697a13144ffSStefano Zampini     if (sfvleaves[i]) {
698a13144ffSStefano Zampini       vmarks[cum++] = i;
699a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
700a13144ffSStefano Zampini     }
7014e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
702a13144ffSStefano Zampini   }
7034e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
704a13144ffSStefano Zampini   if (print) {
705a13144ffSStefano Zampini     IS tbz;
706a13144ffSStefano Zampini 
707a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
7084e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
709a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
710a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
711a13144ffSStefano Zampini   }
712a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
713a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
714a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
715a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
716a13144ffSStefano Zampini 
717a13144ffSStefano Zampini   /* Recompute G */
718a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
719a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
720a13144ffSStefano Zampini   if (print) {
721a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
722a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
723a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
724a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
725a13144ffSStefano Zampini   }
726a13144ffSStefano Zampini 
727a13144ffSStefano Zampini   /* Get primal dofs (if any) */
728a13144ffSStefano Zampini   cum = 0;
729a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
730a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
731a13144ffSStefano Zampini   }
732c2151214SStefano Zampini   if (fl2g) {
733c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
734c2151214SStefano Zampini   }
735a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
736a13144ffSStefano Zampini   if (print) {
737a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
738a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
739a13144ffSStefano Zampini   }
740a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
741c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
742a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
743a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
744a13144ffSStefano Zampini 
745a13144ffSStefano Zampini   /* Compute edge connectivity */
746a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
747a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
748a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
749c2151214SStefano Zampini   if (fl2g) {
750c2151214SStefano Zampini     PetscBT   btf;
751c2151214SStefano Zampini     PetscInt  *iia,*jja,*iiu,*jju;
752c2151214SStefano Zampini     PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
753c2151214SStefano Zampini 
754c2151214SStefano Zampini     /* create CSR for all local dofs */
755c2151214SStefano Zampini     ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
756c2151214SStefano Zampini     if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
757c2151214SStefano 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);
758c2151214SStefano Zampini       iiu = pcbddc->mat_graph->xadj;
759c2151214SStefano Zampini       jju = pcbddc->mat_graph->adjncy;
760c2151214SStefano Zampini     } else if (pcbddc->use_local_adj) {
761c2151214SStefano Zampini       rest = PETSC_TRUE;
762c2151214SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
763c2151214SStefano Zampini     } else {
764c2151214SStefano Zampini       free   = PETSC_TRUE;
765c2151214SStefano Zampini       ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
766c2151214SStefano Zampini       iiu[0] = 0;
767c2151214SStefano Zampini       for (i=0;i<n;i++) {
768c2151214SStefano Zampini         iiu[i+1] = i+1;
769c2151214SStefano Zampini         jju[i]   = -1;
770d904f53bSStefano Zampini       }
771c2151214SStefano Zampini     }
772c2151214SStefano Zampini 
773c2151214SStefano Zampini     /* import sizes of CSR */
774c2151214SStefano Zampini     iia[0] = 0;
775c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
776c2151214SStefano Zampini 
777c2151214SStefano Zampini     /* overwrite entries corresponding to the Nedelec field */
778c2151214SStefano Zampini     ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
779c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
780c2151214SStefano Zampini     for (i=0;i<ne;i++) {
781c2151214SStefano Zampini       ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
782c2151214SStefano Zampini       iia[idxs[i]+1] = ii[i+1]-ii[i];
783c2151214SStefano Zampini     }
784c2151214SStefano Zampini 
785c2151214SStefano Zampini     /* iia in CSR */
786c2151214SStefano Zampini     for (i=0;i<n;i++) iia[i+1] += iia[i];
787c2151214SStefano Zampini 
788c2151214SStefano Zampini     /* jja in CSR */
789c2151214SStefano Zampini     ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
790c2151214SStefano Zampini     for (i=0;i<n;i++)
791c2151214SStefano Zampini       if (!PetscBTLookup(btf,i))
792c2151214SStefano Zampini         for (j=0;j<iiu[i+1]-iiu[i];j++)
793c2151214SStefano Zampini           jja[iia[i]+j] = jju[iiu[i]+j];
794c2151214SStefano Zampini 
795c2151214SStefano Zampini     /* map edge dofs connectivity */
7961e0482f5SStefano Zampini     if (jj) {
797c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
798c2151214SStefano Zampini       for (i=0;i<ne;i++) {
799c2151214SStefano Zampini         PetscInt e = idxs[i];
800c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
801c2151214SStefano Zampini       }
8021e0482f5SStefano Zampini     }
803c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
804c2151214SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
805c2151214SStefano Zampini     if (rest) {
806c2151214SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
807c2151214SStefano Zampini     }
808c2151214SStefano Zampini     if (free) {
809c2151214SStefano Zampini       ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
810c2151214SStefano Zampini     }
811c2151214SStefano Zampini     ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
812c2151214SStefano Zampini   } else {
8131e0482f5SStefano Zampini     if (jj) {
814c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
815c2151214SStefano Zampini     }
816c2151214SStefano Zampini   }
817c2151214SStefano Zampini 
818a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
819a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
820a13144ffSStefano Zampini 
821a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
822c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
823a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
824a13144ffSStefano Zampini 
825c2151214SStefano Zampini   if (fl2g) {
826c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
827c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
828c2151214SStefano Zampini     for (i=0;i<nee;i++) {
829c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
830c2151214SStefano Zampini     }
831c2151214SStefano Zampini   } else {
832c2151214SStefano Zampini     eedges  = alleedges;
833c2151214SStefano Zampini     primals = allprimals;
834c2151214SStefano Zampini   }
835c2151214SStefano Zampini 
836a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
837a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
838c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
839c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
840c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
841c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
842c2151214SStefano Zampini   if (print) {
843c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
844c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
845c2151214SStefano Zampini   }
846c2151214SStefano Zampini 
847c2151214SStefano Zampini   maxsize = 0;
848a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
849a13144ffSStefano Zampini     PetscInt size,mark = i+1;
850a13144ffSStefano Zampini 
851a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
852a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
853a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
854a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
855a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
856a13144ffSStefano Zampini   }
857a13144ffSStefano Zampini 
858a13144ffSStefano Zampini   /* Find coarse edge endpoints */
859a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
860a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
861a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
862a13144ffSStefano Zampini     PetscInt mark = i+1,size;
863a13144ffSStefano Zampini 
864a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8651e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
8661e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
867a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
868a13144ffSStefano Zampini     if (print) {
869a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
870a13144ffSStefano Zampini       ISView(eedges[i],NULL);
871a13144ffSStefano Zampini     }
872a13144ffSStefano Zampini     for (j=0;j<size;j++) {
873a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
874a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
875a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
876a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
877a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
878a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
879a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
880a13144ffSStefano Zampini           PetscInt  k2;
881a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
882a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
883c2151214SStefano 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]));
884c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
885c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
886c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
887a13144ffSStefano Zampini               corner = PETSC_TRUE;
888a13144ffSStefano Zampini               break;
889a13144ffSStefano Zampini             }
890a13144ffSStefano Zampini           }
891a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
892a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
893a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
894a13144ffSStefano Zampini           } else {
895a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
896a13144ffSStefano Zampini           }
897a13144ffSStefano Zampini         }
898a13144ffSStefano Zampini       }
899a13144ffSStefano Zampini     }
900a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
901a13144ffSStefano Zampini   }
902a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
903a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
904c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
905a13144ffSStefano Zampini 
906a13144ffSStefano Zampini   /* Reset marked primal dofs */
907a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
908a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
909a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
910a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
911a13144ffSStefano Zampini 
9120569b399SStefano Zampini   /* Now use the initial lG */
9130569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
9140569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
9150569b399SStefano Zampini   lG   = lGinit;
9160569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
9170569b399SStefano Zampini 
918a13144ffSStefano Zampini   /* Compute extended cols indices */
919b03ebc13SStefano Zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
920b03ebc13SStefano Zampini   ierr = PetscBTCreate(nee,&bter);CHKERRQ(ierr);
921a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
922a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
923a13144ffSStefano Zampini   i   *= maxsize;
924b03ebc13SStefano Zampini   ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
925a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
926a13144ffSStefano Zampini   eerr = PETSC_FALSE;
927a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
928b03ebc13SStefano Zampini     PetscInt size,found = 0;
929a13144ffSStefano Zampini 
930a13144ffSStefano Zampini     cum  = 0;
931a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
9321e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
9331e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
934a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
935b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
936a13144ffSStefano Zampini     for (j=0;j<size;j++) {
937a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
938b03ebc13SStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
939b03ebc13SStefano Zampini         PetscInt vv = jj[k];
940b03ebc13SStefano Zampini         if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv;
941b03ebc13SStefano Zampini         else if (!PetscBTLookupSet(btvc,vv)) found++;
942b03ebc13SStefano Zampini       }
943a13144ffSStefano Zampini     }
944a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
945a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
946a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
947a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
948a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
949a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
950a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
951b03ebc13SStefano Zampini     if (cum != size -1 || found != 2) {
952b03ebc13SStefano Zampini       ierr = PetscBTSet(bter,i);CHKERRQ(ierr);
953a13144ffSStefano Zampini       if (print) {
954a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
955a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
956a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
957a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
958a13144ffSStefano Zampini       }
959a13144ffSStefano Zampini       eerr = PETSC_TRUE;
960a13144ffSStefano Zampini     }
961a13144ffSStefano Zampini   }
9624e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
963a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
964a13144ffSStefano Zampini   if (done) {
965a13144ffSStefano Zampini     PetscInt *newprimals;
966a13144ffSStefano Zampini 
967a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
968a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
969a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
970a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
971a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
9720569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
973b03ebc13SStefano Zampini     if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %d)\n",eerr);
974a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
975b03ebc13SStefano Zampini       PetscBool has_candidates = PETSC_FALSE;
976b03ebc13SStefano Zampini       if (PetscBTLookup(bter,i)) {
977a13144ffSStefano Zampini         PetscInt size,mark = i+1;
978a13144ffSStefano Zampini 
979a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
980a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
981c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
982a13144ffSStefano Zampini         for (j=0;j<size;j++) {
983a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
984b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %d [%d %d)\n",ee,ii[ee],ii[ee+1]);
985a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
986a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
987a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
988a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
989b03ebc13SStefano Zampini               has_candidates = PETSC_TRUE;
990b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Candidate set to vertex %d\n",vv);
991a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
992a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
993a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
994a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
995a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
996b03ebc13SStefano Zampini                   if (print) PetscPrintf(PETSC_COMM_SELF,"    Connected edge dof set to primal %d\n",ee2);
997a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
998a13144ffSStefano Zampini                   /* finally set the new corners */
999a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
1000b03ebc13SStefano Zampini                     if (print) PetscPrintf(PETSC_COMM_SELF,"      Connected nodal dof set to vertex %d\n",jj[k3]);
1001a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
1002a13144ffSStefano Zampini                   }
1003a13144ffSStefano Zampini                 }
1004a13144ffSStefano Zampini               }
1005b03ebc13SStefano Zampini             } else {
1006b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Not a candidate vertex %d\n",jj[k]);
1007a13144ffSStefano Zampini             }
1008a13144ffSStefano Zampini           }
1009a13144ffSStefano Zampini         }
1010b03ebc13SStefano Zampini         if (!has_candidates) { /* circular edge */
1011b03ebc13SStefano Zampini           PetscInt k, ee = idxs[0],*tmarks;
1012b03ebc13SStefano Zampini 
1013b03ebc13SStefano Zampini           ierr = PetscCalloc1(ne,&tmarks);CHKERRQ(ierr);
1014b03ebc13SStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"  Circular edge %d\n",i);
1015b03ebc13SStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
1016b03ebc13SStefano Zampini             PetscInt k2;
1017b03ebc13SStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"    Set to corner %d\n",jj[k]);
1018b03ebc13SStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
1019b03ebc13SStefano Zampini             for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++;
1020b03ebc13SStefano Zampini           }
1021b03ebc13SStefano Zampini           for (j=0;j<size;j++) {
1022b03ebc13SStefano Zampini             if (tmarks[idxs[j]] > 1) {
1023b03ebc13SStefano Zampini               if (print) PetscPrintf(PETSC_COMM_SELF,"  Edge dof set to primal %d\n",idxs[j]);
1024b03ebc13SStefano Zampini               newprimals[cum++] = idxs[j];
1025b03ebc13SStefano Zampini             }
1026b03ebc13SStefano Zampini           }
1027b03ebc13SStefano Zampini           ierr = PetscFree(tmarks);CHKERRQ(ierr);
1028b03ebc13SStefano Zampini         }
1029a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1030a13144ffSStefano Zampini       }
1031a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1032a13144ffSStefano Zampini     }
1033b03ebc13SStefano Zampini     ierr = PetscFree(extcols);CHKERRQ(ierr);
10340569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
1035a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
1036c2151214SStefano Zampini     if (fl2g) {
1037c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
1038c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
1039c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1040c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1041c2151214SStefano Zampini       }
1042c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
1043c2151214SStefano Zampini     }
1044c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1045a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
1046a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
1047a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
1048a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1049a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
1050c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1051c2151214SStefano Zampini     if (fl2g) {
1052c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
1053c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
1054c2151214SStefano Zampini       for (i=0;i<nee;i++) {
1055c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
1056c2151214SStefano Zampini       }
1057c2151214SStefano Zampini     } else {
1058c2151214SStefano Zampini       eedges  = alleedges;
1059c2151214SStefano Zampini       primals = allprimals;
1060c2151214SStefano Zampini     }
1061b03ebc13SStefano Zampini     ierr = PetscCalloc1(nee,&extcols);CHKERRQ(ierr);
1062a13144ffSStefano Zampini 
1063a13144ffSStefano Zampini     /* Mark again */
1064a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
1065a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1066a13144ffSStefano Zampini       PetscInt size,mark = i+1;
1067a13144ffSStefano Zampini 
1068a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
1069a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1070a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
1071a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1072a13144ffSStefano Zampini     }
1073a13144ffSStefano Zampini     if (print) {
1074a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
1075a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
1076a13144ffSStefano Zampini     }
1077a13144ffSStefano Zampini 
1078a13144ffSStefano Zampini     /* Recompute extended cols */
1079a13144ffSStefano Zampini     eerr = PETSC_FALSE;
1080a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
1081a13144ffSStefano Zampini       PetscInt size;
1082a13144ffSStefano Zampini 
1083a13144ffSStefano Zampini       cum  = 0;
1084a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
10851e0482f5SStefano Zampini       if (!size && nedfieldlocal) continue;
10861e0482f5SStefano Zampini       if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
1087a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1088a13144ffSStefano Zampini       for (j=0;j<size;j++) {
1089a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
10901e0482f5SStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
1091a13144ffSStefano Zampini       }
1092a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1093a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
1094a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
1095a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
1096a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
1097a13144ffSStefano Zampini       if (cum != size -1) {
1098a13144ffSStefano Zampini         if (print) {
1099a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
1100a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
1101a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
1102a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
1103a13144ffSStefano Zampini         }
1104a13144ffSStefano Zampini         eerr = PETSC_TRUE;
1105a13144ffSStefano Zampini       }
1106a13144ffSStefano Zampini     }
1107a13144ffSStefano Zampini   }
1108a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1109a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
1110b03ebc13SStefano Zampini   ierr = PetscBTDestroy(&bter);CHKERRQ(ierr);
11117d871cd7SStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
1112a13144ffSStefano Zampini   /* an error should not occur at this point */
1113a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
1114a13144ffSStefano Zampini 
11154e64d54eSstefano_zampini   /* Check the number of endpoints */
11160569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1117b03ebc13SStefano Zampini   ierr = PetscMalloc1(2*nee,&corners);CHKERRQ(ierr);
1118b03ebc13SStefano Zampini   ierr = PetscMalloc1(nee,&cedges);CHKERRQ(ierr);
11194e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
1120b03ebc13SStefano Zampini     PetscInt size, found = 0, gc[2];
11214e64d54eSstefano_zampini 
1122b03ebc13SStefano Zampini     /* init with defaults */
1123b03ebc13SStefano Zampini     cedges[i] = corners[i*2] = corners[i*2+1] = -1;
11244e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
11251e0482f5SStefano Zampini     if (!size && nedfieldlocal) continue;
11261e0482f5SStefano Zampini     if (!size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %d",i);
11274e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
1128b03ebc13SStefano Zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
11294e64d54eSstefano_zampini     for (j=0;j<size;j++) {
11304e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
11314e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
11324e64d54eSstefano_zampini         PetscInt vv = jj[k];
11334e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
1134b03ebc13SStefano Zampini           if (found == 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %d\n",i);
1135b03ebc13SStefano Zampini           corners[i*2+found++] = vv;
11364e64d54eSstefano_zampini         }
11374e64d54eSstefano_zampini       }
11384e64d54eSstefano_zampini     }
1139b03ebc13SStefano Zampini     if (found != 2) {
1140b03ebc13SStefano Zampini       PetscInt e;
1141b03ebc13SStefano Zampini       if (fl2g) {
1142b03ebc13SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,1,idxs,&e);CHKERRQ(ierr);
1143b03ebc13SStefano Zampini       } else {
1144b03ebc13SStefano Zampini         e = idxs[0];
1145b03ebc13SStefano Zampini       }
1146b03ebc13SStefano Zampini       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d (astart %d, estart %d)\n",found,i,e,idxs[0]);
1147b03ebc13SStefano Zampini     }
1148eee23b56SStefano Zampini 
1149eee23b56SStefano Zampini     /* get primal dof index on this coarse edge */
1150b03ebc13SStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc);CHKERRQ(ierr);
1151b03ebc13SStefano Zampini     if (gc[0] > gc[1]) {
1152b03ebc13SStefano Zampini       PetscInt swap  = corners[2*i];
1153b03ebc13SStefano Zampini       corners[2*i]   = corners[2*i+1];
1154b03ebc13SStefano Zampini       corners[2*i+1] = swap;
1155b03ebc13SStefano Zampini     }
1156eee23b56SStefano Zampini     cedges[i] = idxs[size-1];
11574e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
1158b03ebc13SStefano 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]);
11594e64d54eSstefano_zampini   }
11600569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
11614e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
11624e64d54eSstefano_zampini 
1163a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
1164a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
1165a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
1166a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
1167a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1168a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1169a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
1170a13144ffSStefano Zampini 
1171a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1172a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
1173a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
1174a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
1175a13144ffSStefano Zampini       if (emax < emarks[j]) {
1176a13144ffSStefano Zampini         emax = emarks[j];
1177a13144ffSStefano Zampini         eemax = j;
1178a13144ffSStefano Zampini       }
1179a13144ffSStefano Zampini     }
1180a13144ffSStefano Zampini     /* not relevant for edges */
1181a13144ffSStefano Zampini     if (!eemax) continue;
1182a13144ffSStefano Zampini 
1183a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
1184a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
1185c2151214SStefano 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]);
1186a13144ffSStefano Zampini       }
1187a13144ffSStefano Zampini     }
1188a13144ffSStefano Zampini   }
1189a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
1190a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1191a13144ffSStefano Zampini #endif
1192a13144ffSStefano Zampini 
1193a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
1194a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1195a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
1196a13144ffSStefano Zampini   extmem *= maxsize;
1197a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
1198a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
1199a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
1200a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
1201a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
1202a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
1203a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
1204a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
1205a13144ffSStefano Zampini         mark = marks[jj[j]];
1206a13144ffSStefano Zampini 
1207a13144ffSStefano Zampini     /* not relevant */
1208a13144ffSStefano Zampini     if (!mark) continue;
1209a13144ffSStefano Zampini 
1210a13144ffSStefano Zampini     /* import extended row */
1211a13144ffSStefano Zampini     mark--;
1212a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
1213a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
1214a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
1215a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
1216a13144ffSStefano Zampini     extrowcum[mark] += size;
1217a13144ffSStefano Zampini   }
1218a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
1219a13144ffSStefano Zampini   cum  = 0;
1220a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1221a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
1222a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
1223a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
1224a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
1225a13144ffSStefano Zampini   }
1226a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
1227a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
1228a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
1229a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
1230a13144ffSStefano Zampini 
1231a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
1232a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
1233a13144ffSStefano Zampini 
1234a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
1235a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1236c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
1237c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
1238a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
1239a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
1240a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
12411e0482f5SStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,al2g,al2g);CHKERRQ(ierr);
1242a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
1243a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1244a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
1245a13144ffSStefano Zampini 
1246a13144ffSStefano Zampini   /* Defaults to identity */
1247c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
1248a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
1249a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
1250a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
1251a13144ffSStefano Zampini 
12521e0482f5SStefano Zampini   /* Create discrete gradient for the coarser level if needed */
12531e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
12541e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
12551e0482f5SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
12561e0482f5SStefano Zampini     ISLocalToGlobalMapping cel2g,cvl2g;
12571e0482f5SStefano Zampini     IS                     wis,gwis;
12581e0482f5SStefano Zampini     PetscInt               cnv,cne;
12591e0482f5SStefano Zampini 
12601e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis);CHKERRQ(ierr);
12611e0482f5SStefano Zampini     if (fl2g) {
12621e0482f5SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal);CHKERRQ(ierr);
12631e0482f5SStefano Zampini     } else {
12641e0482f5SStefano Zampini       ierr = PetscObjectReference((PetscObject)wis);CHKERRQ(ierr);
12651e0482f5SStefano Zampini       pcbddc->nedclocal = wis;
12661e0482f5SStefano Zampini     }
12671e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis);CHKERRQ(ierr);
12681e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12691e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cne,&wis);CHKERRQ(ierr);
12701e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cel2g);CHKERRQ(ierr);
12711e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12721e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12731e0482f5SStefano Zampini 
12741e0482f5SStefano Zampini     ierr = ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis);CHKERRQ(ierr);
12751e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis);CHKERRQ(ierr);
12761e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12771e0482f5SStefano Zampini     ierr = ISRenumber(gwis,NULL,&cnv,&wis);CHKERRQ(ierr);
12781e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(wis,&cvl2g);CHKERRQ(ierr);
12791e0482f5SStefano Zampini     ierr = ISDestroy(&wis);CHKERRQ(ierr);
12801e0482f5SStefano Zampini     ierr = ISDestroy(&gwis);CHKERRQ(ierr);
12811e0482f5SStefano Zampini 
12821e0482f5SStefano Zampini     ierr = MatCreate(comm,&pcbddc->nedcG);CHKERRQ(ierr);
12831e0482f5SStefano Zampini     ierr = MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv);CHKERRQ(ierr);
12841e0482f5SStefano Zampini     ierr = MatSetType(pcbddc->nedcG,MATAIJ);CHKERRQ(ierr);
12851e0482f5SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL);CHKERRQ(ierr);
12861e0482f5SStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL);CHKERRQ(ierr);
12871e0482f5SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g);CHKERRQ(ierr);
12881e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cel2g);CHKERRQ(ierr);
12891e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cvl2g);CHKERRQ(ierr);
12901e0482f5SStefano Zampini   }
12911e0482f5SStefano Zampini 
12921e0482f5SStefano Zampini #if defined(PRINT_GDET)
12931e0482f5SStefano Zampini   inc = 0;
12941e0482f5SStefano Zampini   lev = pcbddc->current_level;
12951e0482f5SStefano Zampini #endif
1296a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
1297a13144ffSStefano Zampini     Mat         Gins = NULL, GKins = NULL;
12981e0482f5SStefano Zampini     IS          cornersis = NULL;
12991e0482f5SStefano Zampini     PetscScalar cvals[2];
1300a13144ffSStefano Zampini 
13011e0482f5SStefano Zampini     if (pcbddc->nedcG) {
13021e0482f5SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis);CHKERRQ(ierr);
13031e0482f5SStefano Zampini     }
13041e0482f5SStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork);CHKERRQ(ierr);
1305a13144ffSStefano Zampini     if (Gins && GKins) {
1306a13144ffSStefano Zampini       PetscScalar    *data;
1307a13144ffSStefano Zampini       const PetscInt *rows,*cols;
1308a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
1309a13144ffSStefano Zampini 
1310a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
1311a13144ffSStefano Zampini       /* H1 */
1312a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
1313a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
1314a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
1315a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
1316a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
1317a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
1318a13144ffSStefano Zampini       /* complement */
1319a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
13201e0482f5SStefano Zampini       if (!ncc) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %d",i);
1321a13144ffSStefano 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);
13221e0482f5SStefano 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);
1323a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1324a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1325a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
13261e0482f5SStefano Zampini 
13271e0482f5SStefano Zampini       /* coarse discrete gradient */
13281e0482f5SStefano Zampini       if (pcbddc->nedcG) {
13291e0482f5SStefano Zampini         PetscInt cols[2];
13301e0482f5SStefano Zampini 
13311e0482f5SStefano Zampini         cols[0] = 2*i;
13321e0482f5SStefano Zampini         cols[1] = 2*i+1;
13331e0482f5SStefano Zampini         ierr = MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES);CHKERRQ(ierr);
13341e0482f5SStefano Zampini       }
1335a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1336a13144ffSStefano Zampini     }
1337a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1338a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
13391e0482f5SStefano Zampini     ierr = ISDestroy(&cornersis);CHKERRQ(ierr);
1340a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1341a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1342a13144ffSStefano Zampini   }
1343a13144ffSStefano Zampini 
1344a13144ffSStefano Zampini   /* Start assembling */
1345a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13461e0482f5SStefano Zampini   if (pcbddc->nedcG) {
13471e0482f5SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13481e0482f5SStefano Zampini   }
1349a13144ffSStefano Zampini 
1350a13144ffSStefano Zampini   /* Free */
1351c2151214SStefano Zampini   if (fl2g) {
1352c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1353c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1354c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1355c2151214SStefano Zampini     }
1356c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1357c2151214SStefano Zampini   }
1358eee23b56SStefano Zampini 
1359eee23b56SStefano Zampini   /* hack mat_graph with primal dofs on the coarse edges */
1360eee23b56SStefano Zampini   {
1361eee23b56SStefano Zampini     PCBDDCGraph graph   = pcbddc->mat_graph;
1362eee23b56SStefano Zampini     PetscInt    *oqueue = graph->queue;
1363eee23b56SStefano Zampini     PetscInt    *ocptr  = graph->cptr;
1364eee23b56SStefano Zampini     PetscInt    ncc,*idxs;
1365eee23b56SStefano Zampini 
1366eee23b56SStefano Zampini     /* find first primal edge */
1367eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1368eee23b56SStefano Zampini       ierr = ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1369eee23b56SStefano Zampini     } else {
1370eee23b56SStefano Zampini       if (fl2g) {
1371eee23b56SStefano Zampini         ierr = ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges);CHKERRQ(ierr);
1372eee23b56SStefano Zampini       }
1373eee23b56SStefano Zampini       idxs = cedges;
1374eee23b56SStefano Zampini     }
1375eee23b56SStefano Zampini     cum = 0;
1376eee23b56SStefano Zampini     while (cum < nee && cedges[cum] < 0) cum++;
1377eee23b56SStefano Zampini 
1378eee23b56SStefano Zampini     /* adapt connected components */
1379eee23b56SStefano Zampini     ierr = PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue);CHKERRQ(ierr);
1380eee23b56SStefano Zampini     graph->cptr[0] = 0;
1381eee23b56SStefano Zampini     for (i=0,ncc=0;i<graph->ncc;i++) {
1382eee23b56SStefano Zampini       PetscInt lc = ocptr[i+1]-ocptr[i];
1383eee23b56SStefano Zampini       if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */
1384eee23b56SStefano Zampini         graph->cptr[ncc+1] = graph->cptr[ncc]+1;
1385eee23b56SStefano Zampini         graph->queue[graph->cptr[ncc]] = cedges[cum];
1386eee23b56SStefano Zampini         ncc++;
1387eee23b56SStefano Zampini         lc--;
1388eee23b56SStefano Zampini         cum++;
1389eee23b56SStefano Zampini         while (cum < nee && cedges[cum] < 0) cum++;
1390eee23b56SStefano Zampini       }
1391eee23b56SStefano Zampini       graph->cptr[ncc+1] = graph->cptr[ncc] + lc;
1392eee23b56SStefano Zampini       for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j];
1393eee23b56SStefano Zampini       ncc++;
1394eee23b56SStefano Zampini     }
1395eee23b56SStefano Zampini     graph->ncc = ncc;
1396eee23b56SStefano Zampini     if (pcbddc->nedclocal) {
1397eee23b56SStefano Zampini       ierr = ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs);CHKERRQ(ierr);
1398eee23b56SStefano Zampini     }
1399eee23b56SStefano Zampini     ierr = PetscFree2(ocptr,oqueue);CHKERRQ(ierr);
1400eee23b56SStefano Zampini   }
1401c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1402c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1403eee23b56SStefano Zampini 
1404eee23b56SStefano Zampini 
1405c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1406a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1407a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
1408c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
14091e0482f5SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&al2g);CHKERRQ(ierr);
1410c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1411a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1412b03ebc13SStefano Zampini   ierr = PetscFree(corners);CHKERRQ(ierr);
1413b03ebc13SStefano Zampini   ierr = PetscFree(cedges);CHKERRQ(ierr);
1414a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1415a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1416a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1417a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1418a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1419a13144ffSStefano Zampini 
1420a13144ffSStefano Zampini   /* Complete assembling */
1421a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14221e0482f5SStefano Zampini   if (pcbddc->nedcG) {
14231e0482f5SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14241e0482f5SStefano Zampini #if 0
14251e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G");CHKERRQ(ierr);
14261e0482f5SStefano Zampini     ierr = MatView(pcbddc->nedcG,NULL);CHKERRQ(ierr);
14271e0482f5SStefano Zampini #endif
14281e0482f5SStefano Zampini   }
1429a13144ffSStefano Zampini 
1430a13144ffSStefano Zampini   /* set change of basis */
1431a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
14321e0482f5SStefano Zampini #if 0
14331e0482f5SStefano Zampini   if (pcbddc->current_level) {
14341e0482f5SStefano Zampini     PetscViewer viewer;
14351e0482f5SStefano Zampini     char filename[256];
14361e0482f5SStefano Zampini     Mat  Tned;
14371e0482f5SStefano Zampini     IS   sub;
14381e0482f5SStefano Zampini     PetscInt rst;
14391e0482f5SStefano Zampini 
14401e0482f5SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
14411e0482f5SStefano Zampini     ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
14421e0482f5SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
14431e0482f5SStefano Zampini     if (nedfieldlocal) {
14441e0482f5SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
14451e0482f5SStefano Zampini       for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
14461e0482f5SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
14471e0482f5SStefano Zampini     } else {
14481e0482f5SStefano Zampini       for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
14491e0482f5SStefano Zampini     }
14501e0482f5SStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
14511e0482f5SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
14521e0482f5SStefano Zampini     ierr = MatGetOwnershipRange(pc->pmat,&rst,NULL);CHKERRQ(ierr);
14531e0482f5SStefano Zampini     for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
14541e0482f5SStefano Zampini       if (matis->sf_rootdata[i]) {
14551e0482f5SStefano Zampini         matis->sf_rootdata[cum++] = i + rst;
14561e0482f5SStefano Zampini       }
14571e0482f5SStefano Zampini     }
14581e0482f5SStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%D] LEVEL %d MY ne %d cum %d\n",PetscGlobalRank,pcbddc->current_level,ne,cum);
14591e0482f5SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),cum,matis->sf_rootdata,PETSC_USE_POINTER,&sub);CHKERRQ(ierr);
14601e0482f5SStefano Zampini     ierr = MatGetSubMatrix(T,sub,sub,MAT_INITIAL_MATRIX,&Tned);CHKERRQ(ierr);
14611e0482f5SStefano Zampini     ierr = ISDestroy(&sub);CHKERRQ(ierr);
14621e0482f5SStefano Zampini 
14631e0482f5SStefano Zampini     sprintf(filename,"Change_l%d.m",pcbddc->current_level);
14641e0482f5SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)Tned),filename,&viewer);CHKERRQ(ierr);
14651e0482f5SStefano Zampini     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
14661e0482f5SStefano Zampini     ierr = PetscObjectSetName((PetscObject)Tned,"T");CHKERRQ(ierr);
14671e0482f5SStefano Zampini     ierr = MatView(Tned,viewer);CHKERRQ(ierr);
14681e0482f5SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
14691e0482f5SStefano Zampini     ierr = MatDestroy(&Tned);CHKERRQ(ierr);
14701e0482f5SStefano Zampini   }
14711e0482f5SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
14721e0482f5SStefano Zampini #endif
1473a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1474a13144ffSStefano Zampini 
1475a13144ffSStefano Zampini   PetscFunctionReturn(0);
1476a13144ffSStefano Zampini }
1477a13144ffSStefano Zampini 
1478d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1479d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1480d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1481d8203eabSStefano Zampini #undef __FUNCT__
1482d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1483d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1484d8203eabSStefano Zampini {
1485d8203eabSStefano Zampini   PetscErrorCode ierr;
1486d8203eabSStefano Zampini   PetscInt       i;
1487d8203eabSStefano Zampini 
1488d8203eabSStefano Zampini   PetscFunctionBegin;
1489d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1490d8203eabSStefano Zampini     PetscInt first,last;
1491d8203eabSStefano Zampini 
1492d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
149386fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1494d8203eabSStefano Zampini     if (i>=first && i < last) {
1495d8203eabSStefano Zampini       PetscScalar *data;
1496d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1497d8203eabSStefano Zampini       if (!has_const) {
1498d8203eabSStefano Zampini         data[i-first] = 1.;
1499d8203eabSStefano Zampini       } else {
150086fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
150186fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1502d8203eabSStefano Zampini       }
1503d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1504d8203eabSStefano Zampini     }
1505d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1506d8203eabSStefano Zampini   }
1507d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1508d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1509d8203eabSStefano Zampini     PetscInt first,last;
1510d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1511d8203eabSStefano Zampini     if (i>=first && i < last) {
1512d8203eabSStefano Zampini       PetscScalar *data;
1513d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1514d8203eabSStefano Zampini       if (!has_const) {
1515d8203eabSStefano Zampini         data[i-first] = 0.;
1516d8203eabSStefano Zampini       } else {
151786fa73c5SStefano Zampini         data[2*i-first] = 0.;
151886fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1519d8203eabSStefano Zampini       }
1520d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1521d8203eabSStefano Zampini     }
1522d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1523d8203eabSStefano Zampini   }
1524d8203eabSStefano Zampini   PetscFunctionReturn(0);
1525d8203eabSStefano Zampini }
1526d8203eabSStefano Zampini 
1527669cc0f4SStefano Zampini #undef __FUNCT__
1528669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
15298ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1530669cc0f4SStefano Zampini {
1531a198735bSStefano Zampini   Mat                    loc_divudotp;
1532fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
15338ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1534669cc0f4SStefano Zampini   IS                     *faces,*edges;
1535669cc0f4SStefano Zampini   PetscScalar            *vals;
1536669cc0f4SStefano Zampini   const PetscScalar      *array;
1537669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
15381ae86dd6SStefano Zampini   PetscMPIInt            rank;
1539a198735bSStefano Zampini   PetscErrorCode         ierr;
1540669cc0f4SStefano Zampini 
1541669cc0f4SStefano Zampini   PetscFunctionBegin;
1542669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1543669cc0f4SStefano Zampini   if (graph->twodim) {
1544669cc0f4SStefano Zampini     lmaxneighs = 2;
1545669cc0f4SStefano Zampini   } else {
1546669cc0f4SStefano Zampini     lmaxneighs = 1;
1547669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1548669cc0f4SStefano Zampini       const PetscInt *idxs;
1549669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1550669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1551669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1552669cc0f4SStefano Zampini     }
1553669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1554669cc0f4SStefano Zampini   }
1555669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1556669cc0f4SStefano Zampini   maxsize = 0;
1557669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1558669cc0f4SStefano Zampini     PetscInt nn;
1559669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1560669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1561669cc0f4SStefano Zampini   }
1562669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1563669cc0f4SStefano Zampini     PetscInt nn;
1564669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1565669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1566669cc0f4SStefano Zampini   }
1567669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1568669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1569669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
15708ae0ca82SStefano Zampini   if (!transpose) {
15718ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
15728ae0ca82SStefano Zampini   } else {
15738ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
15748ae0ca82SStefano Zampini   }
1575669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
15761ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1577d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1578669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
15798ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1580669cc0f4SStefano Zampini   }
1581d8203eabSStefano Zampini 
1582669cc0f4SStefano Zampini   /* compute local quad vec */
1583a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
15848ae0ca82SStefano Zampini   if (!transpose) {
1585a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
15868ae0ca82SStefano Zampini   } else {
15878ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
15888ae0ca82SStefano Zampini   }
1589669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
15908ae0ca82SStefano Zampini   if (!transpose) {
1591a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
15928ae0ca82SStefano Zampini   } else {
15938ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
15948ae0ca82SStefano Zampini   }
1595fa23a32eSStefano Zampini   if (vl2l) {
1596fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1597fa23a32eSStefano Zampini   } else {
1598fa23a32eSStefano Zampini     vins = v;
1599fa23a32eSStefano Zampini   }
1600fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1601669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
16029a962809SStefano Zampini 
16031ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
16041ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1605669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1606669cc0f4SStefano Zampini     const PetscInt    *idxs;
1607669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1608669cc0f4SStefano Zampini 
1609669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1610669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1611669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
16121ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1613669cc0f4SStefano Zampini     idx = -(idx+1);
1614669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1615669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1616669cc0f4SStefano Zampini   }
1617669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1618669cc0f4SStefano Zampini     const PetscInt    *idxs;
1619669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1620669cc0f4SStefano Zampini 
1621669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1622669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1623669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
16241ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1625669cc0f4SStefano Zampini     idx = -(idx+1);
1626669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1627669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1628669cc0f4SStefano Zampini   }
1629c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1630fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1631fa23a32eSStefano Zampini   if (vl2l) {
1632fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1633fa23a32eSStefano Zampini   }
1634669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1635669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1636669cc0f4SStefano Zampini 
1637669cc0f4SStefano Zampini   /* assemble near null space */
1638669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1639669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1640669cc0f4SStefano Zampini   }
1641669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1642669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1643669cc0f4SStefano Zampini   }
1644669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1645669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1646669cc0f4SStefano Zampini }
1647669cc0f4SStefano Zampini 
1648669cc0f4SStefano Zampini 
1649a3df083aSStefano Zampini #undef __FUNCT__
16501f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
16511f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
16521f4df5f7SStefano Zampini {
16531f4df5f7SStefano Zampini   PetscErrorCode ierr;
16541f4df5f7SStefano Zampini   Vec            local,global;
16551f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16561f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
16571f4df5f7SStefano Zampini 
16581f4df5f7SStefano Zampini   PetscFunctionBegin;
16591f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
16601f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
16611f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
16621f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
16631f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
16641f4df5f7SStefano Zampini       PetscInt i;
16651f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16661f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
16671f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16681f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
16691f4df5f7SStefano Zampini       }
16701f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
16711f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
16721f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
16731f4df5f7SStefano Zampini     }
16741f4df5f7SStefano Zampini   } else {
1675986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
16761f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1677986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1678986cdee1SStefano Zampini       if (i > 1) {
1679986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
16801f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
16811f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
16821f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
16831f4df5f7SStefano Zampini         }
16841f4df5f7SStefano Zampini       }
16851f4df5f7SStefano Zampini     }
1686986cdee1SStefano Zampini   }
16871f4df5f7SStefano Zampini 
16881f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
16891f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
16901f4df5f7SStefano Zampini   }
16911f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
16921f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
16931f4df5f7SStefano Zampini   }
16941f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
16951f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
16961f4df5f7SStefano Zampini   }
16971f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
16981f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
16991f4df5f7SStefano Zampini   PetscFunctionReturn(0);
17001f4df5f7SStefano Zampini }
17011f4df5f7SStefano Zampini 
17021f4df5f7SStefano Zampini #undef __FUNCT__
17033e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
17043e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
17053e589ea0SStefano Zampini {
17063e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
17073e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
17083e589ea0SStefano Zampini   PetscErrorCode    ierr;
17093e589ea0SStefano Zampini 
17103e589ea0SStefano Zampini   PetscFunctionBegin;
17113e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
17123e589ea0SStefano Zampini     PetscFunctionReturn(0);
17133e589ea0SStefano Zampini   }
17143e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17153e589ea0SStefano Zampini     Vec swap;
17163e589ea0SStefano Zampini 
17173e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
17183e589ea0SStefano Zampini     swap = pcbddc->work_change;
17193e589ea0SStefano Zampini     pcbddc->work_change = r;
17203e589ea0SStefano Zampini     r = swap;
17213e589ea0SStefano Zampini   }
17223e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17233e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17243e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
17253e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
17263e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17273e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17283e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1729f913dca9SStefano Zampini     pcbddc->work_change = r;
17303e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
17313e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
17323e589ea0SStefano Zampini   }
17333e589ea0SStefano Zampini   PetscFunctionReturn(0);
17343e589ea0SStefano Zampini }
17353e589ea0SStefano Zampini 
17363e589ea0SStefano Zampini #undef __FUNCT__
1737a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1738a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1739a3df083aSStefano Zampini {
1740a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1741a3df083aSStefano Zampini   PetscErrorCode          ierr;
1742a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1743a3df083aSStefano Zampini 
1744a3df083aSStefano Zampini   PetscFunctionBegin;
1745a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1746a3df083aSStefano Zampini   if (transpose) {
1747a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1748a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1749a3df083aSStefano Zampini   } else {
1750a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1751a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1752a3df083aSStefano Zampini   }
1753a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1754a3df083aSStefano Zampini   if (apply_right) {
1755a3df083aSStefano Zampini     const PetscScalar *ax;
1756a3df083aSStefano Zampini     PetscInt          nl,i;
1757a3df083aSStefano Zampini 
1758a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1759a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1760a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1761a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1762a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1763a3df083aSStefano Zampini       PetscScalar    sum,val;
1764a3df083aSStefano Zampini       const PetscInt *idxs;
1765a3df083aSStefano Zampini       PetscInt       nz,j;
1766a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1767a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1768a3df083aSStefano Zampini       sum = 0.;
1769a3df083aSStefano Zampini       if (ctx->apply_p0) {
1770a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1771a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1772a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1773a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1774a3df083aSStefano Zampini         }
1775a3df083aSStefano Zampini       } else {
1776a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1777a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1778a3df083aSStefano Zampini         }
1779a3df083aSStefano Zampini       }
1780a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1781a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1782a3df083aSStefano Zampini     }
1783a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1784a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1785a3df083aSStefano Zampini   }
1786a3df083aSStefano Zampini   if (transpose) {
1787a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1788a3df083aSStefano Zampini   } else {
1789a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1790a3df083aSStefano Zampini   }
1791a3df083aSStefano Zampini   if (reset_x) {
1792a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1793a3df083aSStefano Zampini   }
1794a3df083aSStefano Zampini   if (apply_left) {
1795a3df083aSStefano Zampini     PetscScalar *ay;
1796a3df083aSStefano Zampini     PetscInt    i;
1797a3df083aSStefano Zampini 
1798a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1799a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1800a3df083aSStefano Zampini       PetscScalar    sum,val;
1801a3df083aSStefano Zampini       const PetscInt *idxs;
1802a3df083aSStefano Zampini       PetscInt       nz,j;
1803a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1804a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1805a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1806a3df083aSStefano Zampini       if (ctx->apply_p0) {
1807a3df083aSStefano Zampini         sum = 0.;
1808a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1809a3df083aSStefano Zampini           sum += ay[idxs[j]];
1810a3df083aSStefano Zampini           ay[idxs[j]] += val;
1811a3df083aSStefano Zampini         }
1812a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1813a3df083aSStefano Zampini       } else {
1814a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1815a3df083aSStefano Zampini           ay[idxs[j]] += val;
1816a3df083aSStefano Zampini         }
1817a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1818a3df083aSStefano Zampini       }
1819a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1820a3df083aSStefano Zampini     }
1821a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1822a3df083aSStefano Zampini   }
1823a3df083aSStefano Zampini   PetscFunctionReturn(0);
1824a3df083aSStefano Zampini }
1825a3df083aSStefano Zampini 
1826a3df083aSStefano Zampini #undef __FUNCT__
1827a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1828a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1829a3df083aSStefano Zampini {
1830a3df083aSStefano Zampini   PetscErrorCode ierr;
1831a3df083aSStefano Zampini 
1832a3df083aSStefano Zampini   PetscFunctionBegin;
1833a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1834a3df083aSStefano Zampini   PetscFunctionReturn(0);
1835a3df083aSStefano Zampini }
1836a3df083aSStefano Zampini 
1837a3df083aSStefano Zampini #undef __FUNCT__
1838a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1839a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1840a3df083aSStefano Zampini {
1841a3df083aSStefano Zampini   PetscErrorCode ierr;
1842a3df083aSStefano Zampini 
1843a3df083aSStefano Zampini   PetscFunctionBegin;
1844a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1845a3df083aSStefano Zampini   PetscFunctionReturn(0);
1846a3df083aSStefano Zampini }
1847a3df083aSStefano Zampini 
1848a3df083aSStefano Zampini #undef __FUNCT__
1849a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1850a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1851a3df083aSStefano Zampini {
1852a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1853a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1854a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1855a3df083aSStefano Zampini   PetscErrorCode          ierr;
1856a3df083aSStefano Zampini 
1857a3df083aSStefano Zampini   PetscFunctionBegin;
1858a3df083aSStefano Zampini   if (!restore) {
18591dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1860a3df083aSStefano Zampini     PetscScalar        *work;
1861b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1862a3df083aSStefano Zampini 
18639a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
18649a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1865a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1866a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1867a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1868a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1869a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1870a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1871a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1872a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1873a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1874a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1875a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1876a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1877059032f7SStefano Zampini     if (reuse) {
1878a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
18791dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1880059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1881059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1882059032f7SStefano Zampini       PetscInt               i;
1883059032f7SStefano Zampini 
1884059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1885059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1886059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1887059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1888059032f7SStefano Zampini       }
1889059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
18901dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1891059032f7SStefano Zampini     }
1892a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1893a3df083aSStefano Zampini     ctx->work = work;
1894a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1895a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1896a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1897a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1898a3df083aSStefano Zampini 
1899a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1900a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1901a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1902a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1903a3df083aSStefano Zampini   } else {
19041dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
19051dd7afcfSStefano Zampini       PetscFunctionReturn(0);
19061dd7afcfSStefano Zampini     }
1907a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1908a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1909a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
19101dd7afcfSStefano Zampini     ctx->A = NULL;
19111dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
19121dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
19131dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
19141dd7afcfSStefano Zampini     if (ctx->free) {
1915059032f7SStefano Zampini       PetscInt i;
19161dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1917059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1918059032f7SStefano Zampini       }
1919059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1920059032f7SStefano Zampini     }
1921a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1922a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1923a3df083aSStefano Zampini   }
1924a3df083aSStefano Zampini   PetscFunctionReturn(0);
1925a3df083aSStefano Zampini }
1926a3df083aSStefano Zampini 
1927a3df083aSStefano Zampini /* used just in bddc debug mode */
1928a3df083aSStefano Zampini #undef __FUNCT__
1929a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1930a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1931a3df083aSStefano Zampini {
1932a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1933a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1934a3df083aSStefano Zampini   Mat            An;
1935a3df083aSStefano Zampini   PetscErrorCode ierr;
1936a3df083aSStefano Zampini 
1937a3df083aSStefano Zampini   PetscFunctionBegin;
1938a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1939a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1940a3df083aSStefano Zampini   if (is1) {
1941a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1942a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1943a3df083aSStefano Zampini   } else {
1944a3df083aSStefano Zampini     *B = An;
1945a3df083aSStefano Zampini   }
1946a3df083aSStefano Zampini   PetscFunctionReturn(0);
1947a3df083aSStefano Zampini }
1948a3df083aSStefano Zampini 
19491cf9b237SStefano Zampini /* TODO: add reuse flag */
19501cf9b237SStefano Zampini #undef __FUNCT__
19511cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
19521cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
19531cf9b237SStefano Zampini {
19541cf9b237SStefano Zampini   Mat            Bt;
19551cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
19561cf9b237SStefano Zampini   const PetscInt *ii,*ij;
19571cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
19581cf9b237SStefano Zampini   PetscBool      flg_row;
19591cf9b237SStefano Zampini   PetscErrorCode ierr;
19601cf9b237SStefano Zampini 
19611cf9b237SStefano Zampini   PetscFunctionBegin;
19621cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
19631cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
19641cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
19651cf9b237SStefano Zampini   nnz = n;
19661cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
19671cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
19681cf9b237SStefano Zampini   }
19691cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
19701cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
19711cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
19721cf9b237SStefano Zampini   nnz = 0;
19731cf9b237SStefano Zampini   bii[0] = 0;
19741cf9b237SStefano Zampini   for (i=0;i<n;i++) {
19751cf9b237SStefano Zampini     PetscInt j;
19761cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
19771cf9b237SStefano Zampini       PetscScalar entry = a[j];
19781cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
19791cf9b237SStefano Zampini         bij[nnz] = ij[j];
19801cf9b237SStefano Zampini         bdata[nnz] = entry;
19811cf9b237SStefano Zampini         nnz++;
19821cf9b237SStefano Zampini       }
19831cf9b237SStefano Zampini     }
19841cf9b237SStefano Zampini     bii[i+1] = nnz;
19851cf9b237SStefano Zampini   }
19861cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
19871cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
19881cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
19891cf9b237SStefano Zampini   {
19901cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
19911cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
19921cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
19931cf9b237SStefano Zampini   }
19941cf9b237SStefano Zampini   *B = Bt;
19951cf9b237SStefano Zampini   PetscFunctionReturn(0);
19961cf9b237SStefano Zampini }
19971cf9b237SStefano Zampini 
1998674ae819SStefano Zampini #undef __FUNCT__
19994f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
20004f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
20014f1b2e48SStefano Zampini {
20024f1b2e48SStefano Zampini   Mat                    B;
20034f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
20044f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
20054f1b2e48SStefano Zampini   PCBDDCGraph            graph;
20064f1b2e48SStefano Zampini   PetscInt               i,n;
20074f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
20084f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
20094f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
20104f1b2e48SStefano Zampini   PetscErrorCode         ierr;
20114f1b2e48SStefano Zampini 
20124f1b2e48SStefano Zampini   PetscFunctionBegin;
201363c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
201463c961adSStefano Zampini     *ncc = 0;
201563c961adSStefano Zampini     *cc = NULL;
201663c961adSStefano Zampini     PetscFunctionReturn(0);
201763c961adSStefano Zampini   }
20184f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
20194f1b2e48SStefano Zampini   if (!isseqaij && filter) {
20201cf9b237SStefano Zampini     PetscBool isseqdense;
20211cf9b237SStefano Zampini 
20221cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
20231cf9b237SStefano Zampini     if (!isseqdense) {
20244f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
20251cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
20261cf9b237SStefano Zampini       PetscScalar *array;
20271cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
20281cf9b237SStefano Zampini 
20291cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
20301cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
20311cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
20321cf9b237SStefano Zampini       for (i=0;i<n;i++) {
20331cf9b237SStefano Zampini         PetscInt j;
20341cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
20351cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
20361cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
20371cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
20381cf9b237SStefano Zampini         }
20391cf9b237SStefano Zampini       }
20401cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
20419d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
20421cf9b237SStefano Zampini     }
20434f1b2e48SStefano Zampini   } else {
20444f1b2e48SStefano Zampini     B = A;
20454f1b2e48SStefano Zampini   }
20464f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
20474f1b2e48SStefano Zampini 
20484f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
20494f1b2e48SStefano Zampini   if (filter) {
20504f1b2e48SStefano Zampini     PetscScalar *data;
20514f1b2e48SStefano Zampini     PetscInt    j,cum;
20524f1b2e48SStefano Zampini 
20534f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
20544f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
20554f1b2e48SStefano Zampini     cum = 0;
20564f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
20574f1b2e48SStefano Zampini       PetscInt t;
20584f1b2e48SStefano Zampini 
20594f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
20604f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
20614f1b2e48SStefano Zampini           continue;
20624f1b2e48SStefano Zampini         }
20634f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
20644f1b2e48SStefano Zampini       }
20654f1b2e48SStefano Zampini       t = xadj_filtered[i];
20664f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
20674f1b2e48SStefano Zampini       cum += t;
20684f1b2e48SStefano Zampini     }
20694f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
20704f1b2e48SStefano Zampini   } else {
20714f1b2e48SStefano Zampini     xadj_filtered = NULL;
20724f1b2e48SStefano Zampini     adjncy_filtered = NULL;
20734f1b2e48SStefano Zampini   }
20744f1b2e48SStefano Zampini 
20754f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
20764f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
20774f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
20784f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
20794f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
2080be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
20814f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
20824f1b2e48SStefano Zampini   if (xadj_filtered) {
20834f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
20844f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
20854f1b2e48SStefano Zampini   } else {
20864f1b2e48SStefano Zampini     graph->xadj = xadj;
20874f1b2e48SStefano Zampini     graph->adjncy = adjncy;
20884f1b2e48SStefano Zampini   }
20894f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
20904f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
20914f1b2e48SStefano Zampini   /* partial clean up */
20924f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
20934f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
20941cf9b237SStefano Zampini   if (A != B) {
20954f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
20964f1b2e48SStefano Zampini   }
20974f1b2e48SStefano Zampini 
20984f1b2e48SStefano Zampini   /* get back data */
20991cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
21001cf9b237SStefano Zampini   if (cc) {
21014f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
21024f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
21034f1b2e48SStefano 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);
21044f1b2e48SStefano Zampini     }
21054f1b2e48SStefano Zampini     *cc = cc_n;
21061cf9b237SStefano Zampini   }
21074f1b2e48SStefano Zampini   /* clean up graph */
21084f1b2e48SStefano Zampini   graph->xadj = 0;
21094f1b2e48SStefano Zampini   graph->adjncy = 0;
21104f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
21114f1b2e48SStefano Zampini   PetscFunctionReturn(0);
21124f1b2e48SStefano Zampini }
21134f1b2e48SStefano Zampini 
21144f1b2e48SStefano Zampini #undef __FUNCT__
21155408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
21165408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
21175408967cSStefano Zampini {
21185408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
21195408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
2120dee84bffSStefano Zampini   IS             dirIS = NULL;
21214f1b2e48SStefano Zampini   PetscInt       i;
21225408967cSStefano Zampini   PetscErrorCode ierr;
21235408967cSStefano Zampini 
21245408967cSStefano Zampini   PetscFunctionBegin;
2125dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
21265408967cSStefano Zampini   if (zerodiag) {
21275408967cSStefano Zampini     Mat            A;
21285408967cSStefano Zampini     Vec            vec3_N;
21295408967cSStefano Zampini     PetscScalar    *vals;
21305408967cSStefano Zampini     const PetscInt *idxs;
2131d12d3064SStefano Zampini     PetscInt       nz,*count;
21325408967cSStefano Zampini 
21335408967cSStefano Zampini     /* p0 */
21345408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
21355408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
21365408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
21375408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
21384f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
21395408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21405408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
21415408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
21425408967cSStefano Zampini     /* v_I */
21435408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
21445408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
21455408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21465408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
21475408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
21485408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
21495408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21505408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
21515408967cSStefano Zampini     if (dirIS) {
21525408967cSStefano Zampini       PetscInt n;
21535408967cSStefano Zampini 
21545408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
21555408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
21565408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
21575408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
21585408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
21595408967cSStefano Zampini     }
21605408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
21615408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
21625408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
21635408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2164669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
21655408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
21665408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
21679a962809SStefano 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]));
21685408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
21695408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2170d12d3064SStefano Zampini 
2171d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
2172d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
2173d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2174d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
2175d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2176d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
21779a962809SStefano 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]);
2178d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2179d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
21805408967cSStefano Zampini   }
2181dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
21825408967cSStefano Zampini 
21835408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
21845408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
21854f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
21865408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
21874f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
21885408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2189f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2190f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
2191f2a566d8SStefano 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);
2192f2a566d8SStefano Zampini   }
21935408967cSStefano Zampini   PetscFunctionReturn(0);
21945408967cSStefano Zampini }
21955408967cSStefano Zampini 
21965408967cSStefano Zampini #undef __FUNCT__
2197339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
2198339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
2199339f8db1SStefano Zampini {
2200339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
22014f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
2202b0f5fe93SStefano Zampini   PetscInt       nz,n;
22031f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
22044f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
2205339f8db1SStefano Zampini   PetscErrorCode ierr;
2206339f8db1SStefano Zampini 
2207339f8db1SStefano Zampini   PetscFunctionBegin;
22089f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
22099f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
2210a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
2211a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
2212a3df083aSStefano Zampini   }
2213a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2214a3df083aSStefano Zampini   pcbddc->benign_n = 0;
22151ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
22164f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
22174f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
22184f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
22191ae86dd6SStefano Zampini      since the local Schur complements are already SPD
22204f1b2e48SStefano Zampini   */
22214f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
22224f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
222340fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
22244f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
22254f1b2e48SStefano Zampini 
22264f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
22274f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
22284f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
22294f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
2230ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
223140fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
223240fa8d13SStefano Zampini     if (!sorted) {
223340fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
223440fa8d13SStefano Zampini     }
223540fa8d13SStefano Zampini   } else {
223640fa8d13SStefano Zampini     pressures = NULL;
223740fa8d13SStefano Zampini   }
223897d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
223997d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
224027b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
224197d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
2242339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
2243339f8db1SStefano Zampini   if (!sorted) {
2244339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
2245339f8db1SStefano Zampini   }
2246339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
22474f1b2e48SStefano Zampini   if (!nz) {
22484f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
22494f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
225040fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
225140fa8d13SStefano Zampini   }
22524f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
22534f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
22544f1b2e48SStefano Zampini   zerodiag_subs = NULL;
22554f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
22561f4df5f7SStefano Zampini   n_interior_dofs = 0;
22571f4df5f7SStefano Zampini   interior_dofs = NULL;
22581f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
22591f4df5f7SStefano Zampini     PetscInt n,i,j;
22601f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
22611f4df5f7SStefano Zampini     PetscInt *iwork;
22621f4df5f7SStefano Zampini 
22631f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
22641f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
22651f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
22661f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
226790648384SStefano Zampini     for (i=1;i<n_neigh;i++)
22681f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
22691f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
22701f4df5f7SStefano Zampini     for (i=0;i<n;i++)
22711f4df5f7SStefano Zampini       if (!iwork[i])
22721f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
22731f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
22741f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
22751f4df5f7SStefano Zampini   }
22764f1b2e48SStefano Zampini   if (has_null_pressures) {
22774f1b2e48SStefano Zampini     IS             *subs;
22781f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
22791f4df5f7SStefano Zampini     const PetscInt *idxs;
22801f4df5f7SStefano Zampini     PetscScalar    *array;
22811f4df5f7SStefano Zampini     Vec            *work;
22821f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
22834f1b2e48SStefano Zampini 
22844f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
22854f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
22861f4df5f7SStefano 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) */
22871f4df5f7SStefano Zampini     if (pcbddc->current_level) {
22881f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
22891f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
22901f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
22911f4df5f7SStefano Zampini       /* work[0] = 1_p */
22921f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
22931f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
22941f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
22951f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
22961f4df5f7SStefano Zampini       /* work[0] = 1_v */
22971f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
22981f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
22991f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
23001f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
23011f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
23021f4df5f7SStefano Zampini     }
23034f1b2e48SStefano Zampini     if (nsubs > 1) {
23044f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
23054f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
23064f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
23074f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
23084f1b2e48SStefano Zampini         PetscInt               nl;
23094f1b2e48SStefano Zampini 
23104f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
23114f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
23124f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
23134f1b2e48SStefano Zampini         if (nl) {
23144f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
23154f1b2e48SStefano Zampini 
23161f4df5f7SStefano Zampini           if (pcbddc->current_level) {
23171f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
23181f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
23191f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
23201f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
23211f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
23221f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
23231f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
23241f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
23251f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
23261f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
23271f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
23281f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
23291f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
23301f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
23311f4df5f7SStefano Zampini                 break;
23321f4df5f7SStefano Zampini               }
23331f4df5f7SStefano Zampini             }
23341f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
23351f4df5f7SStefano Zampini           }
23361f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
23371f4df5f7SStefano Zampini             IS       t_bc;
23381f4df5f7SStefano Zampini             PetscInt nzb;
23391f4df5f7SStefano Zampini 
23401f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
23411f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
23421f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
23431f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
23441f4df5f7SStefano Zampini           }
23451f4df5f7SStefano Zampini           if (valid && pressures) {
23464f1b2e48SStefano Zampini             IS t_pressure_subs;
23474f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
23484f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
23494f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
23504f1b2e48SStefano Zampini           }
23514f1b2e48SStefano Zampini           if (valid) {
23524f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
23534f1b2e48SStefano Zampini             pcbddc->benign_n++;
23544f1b2e48SStefano Zampini           } else {
23554f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
23564f1b2e48SStefano Zampini           }
23574f1b2e48SStefano Zampini         }
23584f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
23594f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
23604f1b2e48SStefano Zampini       }
23614f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
23624f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
23631f4df5f7SStefano Zampini 
23641f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
23651f4df5f7SStefano Zampini         PetscInt nzb;
23661f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
23671f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
23681f4df5f7SStefano Zampini       }
23691f4df5f7SStefano Zampini       if (valid && pressures) {
23704f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
23714f1b2e48SStefano Zampini       }
23721f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
23731f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
23741f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
23751f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
23761f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
23771f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
23781f4df5f7SStefano Zampini               valid = PETSC_FALSE;
23791f4df5f7SStefano Zampini               break;
23801f4df5f7SStefano Zampini           }
23811f4df5f7SStefano Zampini         }
23821f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
23831f4df5f7SStefano Zampini       }
23844f1b2e48SStefano Zampini       if (valid) {
23854f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
2386ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
23874f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
23884f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
23894f1b2e48SStefano Zampini       }
23904f1b2e48SStefano Zampini     }
23911f4df5f7SStefano Zampini     if (pcbddc->current_level) {
23921f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
23934f1b2e48SStefano Zampini     }
23941f4df5f7SStefano Zampini   }
23951f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
23964f1b2e48SStefano Zampini 
23974f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2398b9b0e38cSStefano Zampini     PetscInt n;
2399b9b0e38cSStefano Zampini 
24004f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
24014f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
2402b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
2403b9b0e38cSStefano Zampini     if (n) {
24044f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
24054f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
24064f1b2e48SStefano Zampini     }
2407b9b0e38cSStefano Zampini   }
24084f1b2e48SStefano Zampini 
24094f1b2e48SStefano Zampini   /* final check for null pressures */
24104f1b2e48SStefano Zampini   if (zerodiag && pressures) {
24114f1b2e48SStefano Zampini     PetscInt nz,np;
24124f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
24134f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
24144f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
24154f1b2e48SStefano Zampini   }
24164f1b2e48SStefano Zampini 
24174f1b2e48SStefano Zampini   if (recompute_zerodiag) {
24184f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
24194f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
24204f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
24214f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
24224f1b2e48SStefano Zampini     } else {
24234f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
24244f1b2e48SStefano Zampini 
24254f1b2e48SStefano Zampini       nzn = 0;
24264f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
24274f1b2e48SStefano Zampini         PetscInt ns;
24284f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
24294f1b2e48SStefano Zampini         nzn += ns;
24304f1b2e48SStefano Zampini       }
24314f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
24324f1b2e48SStefano Zampini       nzn = 0;
24334f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
24344f1b2e48SStefano Zampini         PetscInt ns,*idxs;
24354f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
24364f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
24374f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
24384f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
24394f1b2e48SStefano Zampini         nzn += ns;
24404f1b2e48SStefano Zampini       }
24414f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
24424f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
24434f1b2e48SStefano Zampini     }
24444f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
24454f1b2e48SStefano Zampini   }
24464f1b2e48SStefano Zampini 
2447669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2448a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2449a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2450a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2451a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2452a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2453a198735bSStefano Zampini 
24541f4df5f7SStefano Zampini     if (pressures) {
24551f4df5f7SStefano Zampini       isused = pressures;
24561f4df5f7SStefano Zampini     } else {
24571f4df5f7SStefano Zampini       isused = zerodiag;
24581f4df5f7SStefano Zampini     }
2459a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2460669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
24611ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
24621ae86dd6SStefano 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");
2463a198735bSStefano Zampini     n_isused = 0;
2464a198735bSStefano Zampini     if (isused) {
2465a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2466a198735bSStefano Zampini     }
2467a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2468a198735bSStefano Zampini     st = st-n_isused;
24691ae86dd6SStefano Zampini     if (n) {
2470a198735bSStefano Zampini       const PetscInt *gidxs;
2471a198735bSStefano Zampini 
2472a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2473a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2474a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2475a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2476a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2477a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
24781ae86dd6SStefano Zampini     } else {
2479a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2480a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2481a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2482a198735bSStefano Zampini     }
2483a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2484a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2485a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2486a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2487a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2488a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2489a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2490a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2491a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2492a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2493a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2494a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2495a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2496a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
24971ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24981ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24991ae86dd6SStefano Zampini   }
2500b3afcdbeSStefano Zampini 
2501b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
25024f1b2e48SStefano Zampini   if (has_null_pressures) {
25034f1b2e48SStefano Zampini     IS             zerodiagc;
25044f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
25054f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
25064f1b2e48SStefano Zampini 
25074f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2508339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2509339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2510339f8db1SStefano Zampini     /* local change of basis for pressures */
2511339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
251297d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2513339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2514339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2515339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
25164f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
25174f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
25184f1b2e48SStefano Zampini       PetscInt nzs,j;
25194f1b2e48SStefano Zampini 
25204f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
25214f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
25224f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
25234f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
25244f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
25254f1b2e48SStefano Zampini     }
2526339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2527339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2528339f8db1SStefano Zampini     /* set identity on velocities */
2529339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2530339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2531339f8db1SStefano Zampini     }
25324f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
25334f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
25349f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
25354f1b2e48SStefano 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);
2536339f8db1SStefano Zampini     /* set change on pressures */
25374f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
25384f1b2e48SStefano Zampini       PetscScalar *array;
25394f1b2e48SStefano Zampini       PetscInt    nzs;
25404f1b2e48SStefano Zampini 
25414f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
25424f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
25434f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2544339f8db1SStefano Zampini         PetscScalar vals[2];
2545339f8db1SStefano Zampini         PetscInt    cols[2];
2546339f8db1SStefano Zampini 
2547339f8db1SStefano Zampini         cols[0] = idxs[i];
25484f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2549339f8db1SStefano Zampini         vals[0] = 1.;
2550b0f5fe93SStefano Zampini         vals[1] = 1.;
25514f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2552339f8db1SStefano Zampini       }
25534f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
25544f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
25554f1b2e48SStefano Zampini       array[nzs-1] = 1.;
25564f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
25574f1b2e48SStefano Zampini       /* store local idxs for p0 */
25584f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
25594f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2560339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
25614f1b2e48SStefano Zampini     }
2562339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2563339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2564a3df083aSStefano Zampini     /* project if needed */
2565a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
25661dd7afcfSStefano Zampini       Mat M;
25671dd7afcfSStefano Zampini 
25681dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2569339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
25701dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
25711dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2572a3df083aSStefano Zampini     }
25734f1b2e48SStefano Zampini     /* store global idxs for p0 */
25744f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2575339f8db1SStefano Zampini   }
2576ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
25774f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2578b0f5fe93SStefano Zampini 
2579b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2580b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
258127b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
258227b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2583339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2584339f8db1SStefano Zampini   PetscFunctionReturn(0);
2585339f8db1SStefano Zampini }
2586339f8db1SStefano Zampini 
2587339f8db1SStefano Zampini #undef __FUNCT__
2588015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2589015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2590efc2fbd9SStefano Zampini {
2591efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2592de9d7bd0SStefano Zampini   PetscScalar    *array;
2593efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2594efc2fbd9SStefano Zampini 
2595efc2fbd9SStefano Zampini   PetscFunctionBegin;
2596efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2597efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
25984f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2599efc2fbd9SStefano Zampini   }
2600de9d7bd0SStefano Zampini   if (get) {
2601efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
26024f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
26034f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2604efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2605de9d7bd0SStefano Zampini   } else {
2606de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2607de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2608de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2609de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2610efc2fbd9SStefano Zampini   }
2611efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2612efc2fbd9SStefano Zampini }
2613efc2fbd9SStefano Zampini 
2614efc2fbd9SStefano Zampini #undef __FUNCT__
2615c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2616c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2617c263805aSStefano Zampini {
2618c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2619c263805aSStefano Zampini   PetscErrorCode ierr;
2620c263805aSStefano Zampini 
2621c263805aSStefano Zampini   PetscFunctionBegin;
2622c263805aSStefano Zampini   /* TODO: add error checking
2623c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2624c263805aSStefano Zampini     - cannot push before pop.
26251c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2626c263805aSStefano Zampini   */
26274f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2628efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2629efc2fbd9SStefano Zampini   }
2630c263805aSStefano Zampini   if (pop) {
2631a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
26324f1b2e48SStefano Zampini       IS       is_p0;
26334f1b2e48SStefano Zampini       MatReuse reuse;
2634c263805aSStefano Zampini 
2635c263805aSStefano Zampini       /* extract B_0 */
26364f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
26374f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
26384f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
26394f1b2e48SStefano Zampini       }
26404f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
26414f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2642c263805aSStefano Zampini       /* remove rows and cols from local problem */
2643c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
264497d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
26454f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
26464f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2647a3df083aSStefano Zampini     } else {
2648a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2649a3df083aSStefano Zampini       PetscScalar *vals;
2650a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2651a3df083aSStefano Zampini 
2652a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2653a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2654a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
26550b5adadeSStefano Zampini         PetscInt *nnz;
2656a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2657a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2658a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2659331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2660331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2661331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2662331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2663331e053bSStefano Zampini         }
2664331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2665331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2666331e053bSStefano Zampini       }
2667a3df083aSStefano Zampini 
2668a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2669a3df083aSStefano Zampini         PetscScalar *array;
2670a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2671a3df083aSStefano Zampini 
2672a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2673a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2674a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2675a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2676a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2677a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2678a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2679a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2680a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2681a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2682a3df083aSStefano Zampini         cum = 0;
2683a3df083aSStefano Zampini         for (j=0;j<n;j++) {
268422db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2685a3df083aSStefano Zampini             vals[cum] = array[j];
2686a3df083aSStefano Zampini             idxs_ins[cum] = j;
2687a3df083aSStefano Zampini             cum++;
2688a3df083aSStefano Zampini           }
2689a3df083aSStefano Zampini         }
2690a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2691a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2692a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2693a3df083aSStefano Zampini       }
2694a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2695a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2696a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2697a3df083aSStefano Zampini     }
2698c263805aSStefano Zampini   } else { /* push */
2699a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
27004f1b2e48SStefano Zampini       PetscInt i;
27014f1b2e48SStefano Zampini 
27024f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
27034f1b2e48SStefano Zampini         PetscScalar *B0_vals;
27044f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
27054f1b2e48SStefano Zampini 
27064f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
27074f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
27087b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
27094f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
27104f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
27114f1b2e48SStefano Zampini       }
2712c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2713c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2714a3df083aSStefano Zampini     } else {
2715a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2716a3df083aSStefano Zampini     }
2717c263805aSStefano Zampini   }
2718c263805aSStefano Zampini   PetscFunctionReturn(0);
2719c263805aSStefano Zampini }
2720c263805aSStefano Zampini 
2721c263805aSStefano Zampini #undef __FUNCT__
2722b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
272308122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2724b1b3d7a2SStefano Zampini {
2725b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
272608122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
272708122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
272808122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
272908122e43SStefano Zampini   PetscScalar     *work,lwork;
273008122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
273108122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
273208122e43SStefano Zampini   PetscReal       *eigs,thresh;
27331b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2734f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
273508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
273608122e43SStefano Zampini   PetscReal       *rwork;
273708122e43SStefano Zampini #endif
2738b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2739b1b3d7a2SStefano Zampini 
2740b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2741b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2742af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2743af25d912SStefano 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);
274406a4e24aSStefano Zampini 
2745fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2746fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2747fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2748fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
27491575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2750fd14bc51SStefano Zampini   }
2751fd14bc51SStefano Zampini 
2752e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2753e496cd5dSStefano 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);
2754e496cd5dSStefano Zampini   }
2755e496cd5dSStefano Zampini 
275608122e43SStefano Zampini   /* max size of subsets */
275708122e43SStefano Zampini   mss = 0;
275808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
275908122e43SStefano Zampini     PetscInt subset_size;
2760862806e4SStefano Zampini 
276108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
276208122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
276308122e43SStefano Zampini   }
276408122e43SStefano Zampini 
276508122e43SStefano Zampini   /* min/max and threshold */
276608122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2767f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
276808122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2769f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2770f6f667cfSStefano Zampini   if (nmin) {
2771f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2772f6f667cfSStefano Zampini   }
277308122e43SStefano Zampini 
277408122e43SStefano Zampini   /* allocate lapack workspace */
277508122e43SStefano Zampini   cum = cum2 = 0;
277608122e43SStefano Zampini   maxneigs = 0;
277708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
277808122e43SStefano Zampini     PetscInt n,subset_size;
2779f6f667cfSStefano Zampini 
278008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
278108122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
27829162d606SStefano Zampini     cum += subset_size;
27839162d606SStefano Zampini     cum2 += subset_size*n;
278408122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
278508122e43SStefano Zampini   }
278608122e43SStefano Zampini   if (mss) {
27879ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
278808122e43SStefano Zampini       PetscBLASInt B_itype = 1;
278908122e43SStefano Zampini       PetscBLASInt B_N = mss;
27904c6709b3SStefano Zampini       PetscReal    zero = 0.0;
27914c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
279208122e43SStefano Zampini 
279308122e43SStefano Zampini       B_lwork = -1;
279408122e43SStefano Zampini       S = NULL;
279508122e43SStefano Zampini       St = NULL;
2796a58a30b4SStefano Zampini       eigs = NULL;
2797a58a30b4SStefano Zampini       eigv = NULL;
2798a58a30b4SStefano Zampini       B_iwork = NULL;
2799a58a30b4SStefano Zampini       B_ifail = NULL;
2800d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2801d1710679SStefano Zampini       rwork = NULL;
2802d1710679SStefano Zampini #endif
28038bec7fa6SStefano Zampini       thresh = 1.0;
280408122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
280508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
280608122e43SStefano 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));
280708122e43SStefano Zampini #else
280808122e43SStefano 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));
280908122e43SStefano Zampini #endif
281008122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
281108122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
281208122e43SStefano Zampini     } else {
281308122e43SStefano Zampini         /* TODO */
281408122e43SStefano Zampini     }
281508122e43SStefano Zampini   } else {
281608122e43SStefano Zampini     lwork = 0;
281708122e43SStefano Zampini   }
281808122e43SStefano Zampini 
281908122e43SStefano Zampini   nv = 0;
2820d62866d3SStefano 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) */
2821d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
282208122e43SStefano Zampini   }
28234c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2824f6f667cfSStefano Zampini   if (allocated_S_St) {
2825f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2826f6f667cfSStefano Zampini   }
2827f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
282808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
282908122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
283008122e43SStefano Zampini #endif
28319162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
28329162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
28339162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
283408122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
28359162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
283608122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
283708122e43SStefano Zampini 
283808122e43SStefano Zampini   maxneigs = 0;
283972b8c272SStefano Zampini   cum = cumarray = 0;
28409162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
28419162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2842d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
284308122e43SStefano Zampini     const PetscInt *idxs;
284408122e43SStefano Zampini 
2845d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
284608122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
284708122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
284808122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
284908122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
28509162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
28519162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
285208122e43SStefano Zampini     }
2853d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
285408122e43SStefano Zampini   }
285508122e43SStefano Zampini 
285608122e43SStefano Zampini   if (mss) { /* multilevel */
285708122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
285808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
285908122e43SStefano Zampini   }
286008122e43SStefano Zampini 
2861ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
286208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
286308122e43SStefano Zampini     const PetscInt *idxs;
28649d54b7f4SStefano Zampini     PetscReal      upper,lower;
2865862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
286608122e43SStefano Zampini     PetscBLASInt   B_N;
2867aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
286808122e43SStefano Zampini 
28699d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
28709d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
28719d54b7f4SStefano Zampini       lower = thresh;
28729d54b7f4SStefano Zampini     } else {
28739d54b7f4SStefano Zampini       upper = 1./thresh;
28749d54b7f4SStefano Zampini       lower = 0.;
28759d54b7f4SStefano Zampini     }
2876862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2877ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2878f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2879f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
28809ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2881aff50787SStefano Zampini         PetscInt j,k;
2882aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2883aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2884aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
288508122e43SStefano Zampini         }
288608122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2887aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2888aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2889aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2890aff50787SStefano Zampini           }
289108122e43SStefano Zampini         }
289208122e43SStefano Zampini       } else {
289308122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
289408122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
289508122e43SStefano Zampini       }
28968bec7fa6SStefano Zampini     } else {
2897f6f667cfSStefano Zampini       S = Sarray + cumarray;
2898f6f667cfSStefano Zampini       St = Starray + cumarray;
28998bec7fa6SStefano Zampini     }
2900aff50787SStefano Zampini     /* see if we can save some work */
2901b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2902aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2903aff50787SStefano Zampini     }
2904aff50787SStefano Zampini 
2905b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2906aff50787SStefano Zampini       B_neigs = 0;
2907aff50787SStefano Zampini     } else {
29089ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
290908122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2910f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
29114c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
29129552c7c7SStefano Zampini         PetscInt     nmin_s;
2913b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
291408122e43SStefano Zampini 
2915fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2916eee23b56SStefano 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]]);
2917fd14bc51SStefano Zampini         }
2918d16cbb6bSStefano Zampini 
2919b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2920b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2921b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2922b7ab4a40SStefano Zampini         }
2923b7ab4a40SStefano Zampini 
292408122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2925b7ab4a40SStefano Zampini         if (compute_range) {
2926d16cbb6bSStefano Zampini 
2927d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
292808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29299d54b7f4SStefano 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));
293008122e43SStefano Zampini #else
29319d54b7f4SStefano 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));
293208122e43SStefano Zampini #endif
2933b7ab4a40SStefano Zampini         } else if (!same_data) {
2934d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2935d16cbb6bSStefano Zampini           B_IL = 1;
2936d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
29379d54b7f4SStefano 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));
2938d16cbb6bSStefano Zampini #else
29399d54b7f4SStefano 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));
2940d16cbb6bSStefano Zampini #endif
2941b03ebc13SStefano Zampini         } else { /* same_data is true, so just get the adaptive functional requested by the user */
2942b7ab4a40SStefano Zampini           PetscInt k;
2943b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2944b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2945b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2946b7ab4a40SStefano Zampini           nmin = nmax;
2947b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2948b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2949b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2950b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2951b7ab4a40SStefano Zampini           }
2952d16cbb6bSStefano Zampini         }
295308122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
295408122e43SStefano Zampini         if (B_ierr) {
29556c4ed002SBarry 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);
29566c4ed002SBarry 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);
29576c4ed002SBarry 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);
295808122e43SStefano Zampini         }
295908122e43SStefano Zampini 
296008122e43SStefano Zampini         if (B_neigs > nmax) {
2961fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2962fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2963fd14bc51SStefano Zampini           }
29649d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
296508122e43SStefano Zampini           B_neigs = nmax;
296608122e43SStefano Zampini         }
296708122e43SStefano Zampini 
29689552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
29699552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
297008122e43SStefano Zampini           PetscBLASInt B_neigs2;
297108122e43SStefano Zampini 
29729d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2973f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
29749d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
29759d54b7f4SStefano Zampini           } else {
29769d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
29779d54b7f4SStefano Zampini             B_IU = nmin_s;
29789d54b7f4SStefano Zampini           }
2979fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2980fd14bc51SStefano 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);
2981fd14bc51SStefano Zampini           }
29829ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
29831ae86dd6SStefano Zampini             PetscInt j,k;
298408122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
29851ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
29861ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
29871ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
298808122e43SStefano Zampini               }
298908122e43SStefano Zampini             }
299008122e43SStefano Zampini           } else {
299108122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
299208122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
299308122e43SStefano Zampini           }
299408122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
299508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
29969d54b7f4SStefano 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));
299708122e43SStefano Zampini #else
29989d54b7f4SStefano 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));
299908122e43SStefano Zampini #endif
300008122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
300108122e43SStefano Zampini           B_neigs += B_neigs2;
300208122e43SStefano Zampini         }
300308122e43SStefano Zampini         if (B_ierr) {
30046c4ed002SBarry 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);
30056c4ed002SBarry 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);
30066c4ed002SBarry 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);
300708122e43SStefano Zampini         }
3008fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
3009ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
301008122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
301108122e43SStefano Zampini             if (eigs[j] == 0.0) {
3012ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
301308122e43SStefano Zampini             } else {
30149d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
3015ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
30169d54b7f4SStefano Zampini               } else {
30179d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
30189d54b7f4SStefano Zampini               }
3019fd14bc51SStefano Zampini             }
302008122e43SStefano Zampini           }
302108122e43SStefano Zampini         }
302208122e43SStefano Zampini       } else {
302308122e43SStefano Zampini           /* TODO */
302408122e43SStefano Zampini       }
3025aff50787SStefano Zampini     }
30266c3e6151SStefano Zampini     /* change the basis back to the original one */
30276c3e6151SStefano Zampini     if (sub_schurs->change) {
302872b8c272SStefano Zampini       Mat change,phi,phit;
30296c3e6151SStefano Zampini 
30306c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
30316c3e6151SStefano Zampini         PetscInt ii;
30326c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
30336c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
30346c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
3035684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3036684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
3037684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
3038684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3039684229deSStefano Zampini #else
30406c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
3041684229deSStefano Zampini #endif
30426c3e6151SStefano Zampini           }
30436c3e6151SStefano Zampini         }
30446c3e6151SStefano Zampini       }
304572b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
30466c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
304772b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
30486c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
30496c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
30506c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
30516c3e6151SStefano Zampini     }
30528bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
30538bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
30549162d606SStefano Zampini     if (B_neigs) {
30559162d606SStefano 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);
3056fd14bc51SStefano Zampini 
3057fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
30589552c7c7SStefano Zampini         PetscInt ii;
30599552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
3060ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
30619552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
3062ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
3063ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3064ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
3065ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
3066ac47001eSStefano Zampini #else
3067ac47001eSStefano 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);
3068ac47001eSStefano Zampini #endif
30699552c7c7SStefano Zampini           }
30709552c7c7SStefano Zampini         }
3071fd14bc51SStefano Zampini       }
30729162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
30739162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
30749162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
30759162d606SStefano Zampini       cum++;
307608122e43SStefano Zampini     }
307708122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
307808122e43SStefano Zampini     /* shift for next computation */
307908122e43SStefano Zampini     cumarray += subset_size*subset_size;
308008122e43SStefano Zampini   }
3081fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
3082fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3083fd14bc51SStefano Zampini   }
308408122e43SStefano Zampini 
308508122e43SStefano Zampini   if (mss) {
308608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
308708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
3088f6f667cfSStefano Zampini     /* destroy matrices (junk) */
3089f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
3090f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
309108122e43SStefano Zampini   }
3092f6f667cfSStefano Zampini   if (allocated_S_St) {
3093f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
3094f6f667cfSStefano Zampini   }
3095f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
309608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
309708122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
309808122e43SStefano Zampini #endif
309908122e43SStefano Zampini   if (pcbddc->dbg_flag) {
31001b968477SStefano Zampini     PetscInt maxneigs_r;
3101b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
31029b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
310308122e43SStefano Zampini   }
310408122e43SStefano Zampini   PetscFunctionReturn(0);
310508122e43SStefano Zampini }
3106b1b3d7a2SStefano Zampini 
3107674ae819SStefano Zampini #undef __FUNCT__
3108c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
3109c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
3110c8587f34SStefano Zampini {
31118629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
3112c8587f34SStefano Zampini   PetscErrorCode ierr;
3113c8587f34SStefano Zampini 
3114c8587f34SStefano Zampini   PetscFunctionBegin;
3115f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
31165e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
3117c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
3118c8587f34SStefano Zampini 
3119684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
31200fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
3121684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3122c8587f34SStefano Zampini 
31238629588bSStefano Zampini   /*
31248629588bSStefano Zampini      Setup local correction and local part of coarse basis.
31258629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
31268629588bSStefano Zampini   */
312747f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
31288629588bSStefano Zampini 
31298629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
31308629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
31318629588bSStefano Zampini 
31328629588bSStefano Zampini   /* free */
31338629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
3134c8587f34SStefano Zampini   PetscFunctionReturn(0);
3135c8587f34SStefano Zampini }
3136c8587f34SStefano Zampini 
3137c8587f34SStefano Zampini #undef __FUNCT__
3138674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
3139674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
3140674ae819SStefano Zampini {
3141674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3142674ae819SStefano Zampini   PetscErrorCode ierr;
3143674ae819SStefano Zampini 
3144674ae819SStefano Zampini   PetscFunctionBegin;
3145674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
314630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3147674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
3148785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3149674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
3150f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3151f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3152785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
315363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
315463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
3155674ae819SStefano Zampini   PetscFunctionReturn(0);
3156674ae819SStefano Zampini }
3157674ae819SStefano Zampini 
3158674ae819SStefano Zampini #undef __FUNCT__
3159674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
3160674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
3161674ae819SStefano Zampini {
3162674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
31634f1b2e48SStefano Zampini   PetscInt       i;
3164674ae819SStefano Zampini   PetscErrorCode ierr;
3165674ae819SStefano Zampini 
3166674ae819SStefano Zampini   PetscFunctionBegin;
31671e0482f5SStefano Zampini   ierr = MatDestroy(&pcbddc->nedcG);CHKERRQ(ierr);
31681e0482f5SStefano Zampini   ierr = ISDestroy(&pcbddc->nedclocal);CHKERRQ(ierr);
3169a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
3170b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3171674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
317216909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
31731dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
3174674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3175669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
3176fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
3177a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
3178674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
31794f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
31804f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
31814f1b2e48SStefano Zampini   }
31824f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
3183b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
3184b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
3185b334f244SStefano Zampini   }
3186c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
31878af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
3188674ae819SStefano Zampini   PetscFunctionReturn(0);
3189674ae819SStefano Zampini }
3190674ae819SStefano Zampini 
3191674ae819SStefano Zampini #undef __FUNCT__
3192674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
3193674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
3194674ae819SStefano Zampini {
3195674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3196674ae819SStefano Zampini   PetscErrorCode ierr;
3197674ae819SStefano Zampini 
3198674ae819SStefano Zampini   PetscFunctionBegin;
3199674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
320058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
3201ca92afb2SStefano Zampini     PetscScalar *array;
320206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
320306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
320458da7f69SStefano Zampini   }
3205674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3206674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
320715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
320815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3209674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
3210674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
3211674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
321206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
3213674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3214674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
32158ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3216674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3217674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3218674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
3219f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
3220f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
3221f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
3222f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3223727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
32240e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3225f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
322670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
322781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
32280369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
32291dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
32304f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
32318b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
3232ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
3233ca92afb2SStefano Zampini     PetscInt i;
3234ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
3235ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
3236ca92afb2SStefano Zampini     }
3237ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
3238ca92afb2SStefano Zampini   }
32394f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
3240674ae819SStefano Zampini   PetscFunctionReturn(0);
3241674ae819SStefano Zampini }
3242674ae819SStefano Zampini 
3243674ae819SStefano Zampini #undef __FUNCT__
3244f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
3245f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
32466bfb1811SStefano Zampini {
32476bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
32486bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
32496bfb1811SStefano Zampini   VecType        impVecType;
32504f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
32516bfb1811SStefano Zampini   PetscErrorCode ierr;
32526bfb1811SStefano Zampini 
32536bfb1811SStefano Zampini   PetscFunctionBegin;
32544f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
3255b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
32566bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
3257e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
3258e7b262bdSStefano Zampini   /* R nodes */
3259e7b262bdSStefano Zampini   old_size = -1;
3260e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
3261e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
3262e7b262bdSStefano Zampini   }
3263e7b262bdSStefano Zampini   if (n_R != old_size) {
3264e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
3265e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
32666bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
32676bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
32686bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
32696bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
3270e7b262bdSStefano Zampini   }
3271e7b262bdSStefano Zampini   /* local primal dofs */
3272e7b262bdSStefano Zampini   old_size = -1;
3273e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
3274e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
3275e7b262bdSStefano Zampini   }
3276e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
3277e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
327883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
3279e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
32806bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
3281e7b262bdSStefano Zampini   }
3282e7b262bdSStefano Zampini   /* local explicit constraints */
3283e7b262bdSStefano Zampini   old_size = -1;
3284e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
3285e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
3286e7b262bdSStefano Zampini   }
3287e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
3288e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
328983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
329083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
329183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
329283b7ccabSStefano Zampini   }
32936bfb1811SStefano Zampini   PetscFunctionReturn(0);
32946bfb1811SStefano Zampini }
32956bfb1811SStefano Zampini 
32966bfb1811SStefano Zampini #undef __FUNCT__
329747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
329847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
329988ebb749SStefano Zampini {
330025084f0cSStefano Zampini   PetscErrorCode  ierr;
330125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
330288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
330388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3304d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
330525084f0cSStefano Zampini   /* submatrices of local problem */
330680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
330706656605SStefano Zampini   /* submatrices of local coarse problem */
330806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
330925084f0cSStefano Zampini   /* working matrices */
331006656605SStefano Zampini   Mat             C_CR;
331125084f0cSStefano Zampini   /* additional working stuff */
331206656605SStefano Zampini   PC              pc_R;
33134f1b2e48SStefano Zampini   Mat             F;
33145cbda25cSStefano Zampini   Vec             dummy_vec;
3315a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
331625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
331706656605SStefano Zampini   PetscScalar     *work;
331806656605SStefano Zampini   PetscInt        *idx_V_B;
3319ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
332006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
3321ffd830a3SStefano Zampini 
332225084f0cSStefano Zampini   /* some shortcuts to scalars */
332306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
332488ebb749SStefano Zampini 
332588ebb749SStefano Zampini   PetscFunctionBegin;
33269a962809SStefano 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");
3327ffd830a3SStefano Zampini 
3328ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
3329b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
33304f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
3331b371cd4fSStefano Zampini   n_B = pcis->n_B;
3332b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
333388ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
333488ebb749SStefano Zampini 
333588ebb749SStefano Zampini   /* vertices in boundary numbering */
3336785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
33370e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
33386c4ed002SBarry 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);
333988ebb749SStefano Zampini 
334006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
3341019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
334206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
334306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
334406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
334506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
334606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
334706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
334806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
334906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
335006656605SStefano Zampini 
335106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
335206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
335306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
335406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
335506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
3356ffd830a3SStefano Zampini   lda_rhs = n_R;
3357a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
335806656605SStefano Zampini   if (isLU || isILU || isCHOL) {
335906656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
3360b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
3361df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3362d62866d3SStefano Zampini     MatFactorType      type;
3363d62866d3SStefano Zampini 
3364df4d28bfSStefano Zampini     F = reuse_solver->F;
33656816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
3366d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
3367ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
336822db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
336906656605SStefano Zampini   } else {
337006656605SStefano Zampini     F = NULL;
337106656605SStefano Zampini   }
337206656605SStefano Zampini 
3373ffd830a3SStefano Zampini   /* allocate workspace */
3374ffd830a3SStefano Zampini   n = 0;
3375ffd830a3SStefano Zampini   if (n_constraints) {
3376ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
3377ffd830a3SStefano Zampini   }
3378ffd830a3SStefano Zampini   if (n_vertices) {
3379ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
3380ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
3381ffd830a3SStefano Zampini   }
3382ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
3383ffd830a3SStefano Zampini 
33845cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
33855cbda25cSStefano Zampini   dummy_vec = NULL;
33865cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
33875cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
33885cbda25cSStefano Zampini   }
33895cbda25cSStefano Zampini 
339088ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
339188ebb749SStefano Zampini   if (n_constraints) {
339272b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
339306656605SStefano Zampini     IS          is_aux;
339480677318SStefano Zampini     PetscScalar *array,*array2;
339506656605SStefano Zampini 
3396f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
339780677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
339888ebb749SStefano Zampini 
339925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
340025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
34018ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
340272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
340388ebb749SStefano Zampini 
340480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
340580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
3406ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
340788ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
340806656605SStefano Zampini       const PetscScalar *row_cmat_values;
340906656605SStefano Zampini       const PetscInt    *row_cmat_indices;
341006656605SStefano Zampini       PetscInt          size_of_constraint,j;
341188ebb749SStefano Zampini 
341206656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
341306656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
3414ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
341506656605SStefano Zampini       }
341606656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
341706656605SStefano Zampini     }
3418ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
341906656605SStefano Zampini     if (F) {
342006656605SStefano Zampini       Mat B;
342106656605SStefano Zampini 
3422ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
3423a3df083aSStefano Zampini       if (need_benign_correction) {
3424df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3425a3df083aSStefano Zampini 
342672b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
342772b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3428a3df083aSStefano Zampini       }
342980677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
3430a3df083aSStefano Zampini       if (need_benign_correction) {
3431a3df083aSStefano Zampini         PetscScalar        *marr;
3432df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3433a3df083aSStefano Zampini 
3434a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
34355cbda25cSStefano Zampini         if (lda_rhs != n_R) {
34365cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
34375cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
34385cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
34395cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
34405cbda25cSStefano Zampini           }
34415cbda25cSStefano Zampini         } else {
3442a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3443a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
34445cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3445a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3446a3df083aSStefano Zampini           }
34475cbda25cSStefano Zampini         }
3448a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3449a3df083aSStefano Zampini       }
345006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
345106656605SStefano Zampini     } else {
345280677318SStefano Zampini       PetscScalar *marr;
345380677318SStefano Zampini 
345480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
345506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3456ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3457ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
345806656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
345906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
346006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
346106656605SStefano Zampini       }
346280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
346306656605SStefano Zampini     }
346480677318SStefano Zampini     if (!pcbddc->switch_static) {
346580677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
346680677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
346780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
346880677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3469ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
347080677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
347180677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347280677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347380677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
347480677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
347580677318SStefano Zampini       }
347680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
347780677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
347872b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
347980677318SStefano Zampini     } else {
3480ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3481ffd830a3SStefano Zampini         IS dummy;
3482ffd830a3SStefano Zampini 
3483ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
348472b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3485ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3486ffd830a3SStefano Zampini       } else {
348780677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
348880677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3489ffd830a3SStefano Zampini       }
349025084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
349180677318SStefano Zampini     }
349280677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
349380677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
349480677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
349506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
349606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
349780677318SStefano Zampini     if (isCHOL) {
349880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
349980677318SStefano Zampini     } else {
350025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
350180677318SStefano Zampini     }
350280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
350306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
350425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
350525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
350625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
350780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
350872b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
350972b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
351006656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
351106656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3512f4ddd8eeSStefano Zampini   }
3513fc227af8SStefano Zampini 
3514fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
351588ebb749SStefano Zampini   if (n_vertices) {
351606656605SStefano Zampini     IS is_aux;
35173a50541eSStefano Zampini 
3518b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
35196816873aSStefano Zampini       IS tis;
35206816873aSStefano Zampini 
35216816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
35226816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
35236816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
35246816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
35256816873aSStefano Zampini     } else {
35263a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
35276816873aSStefano Zampini     }
35289577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
35299577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
353004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
353125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
353288ebb749SStefano Zampini   }
353388ebb749SStefano Zampini 
353488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3535f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
353606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
353706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
353806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
353906656605SStefano Zampini     }
3540f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
354106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
354206656605SStefano Zampini       PetscScalar *marray;
354306656605SStefano Zampini 
354406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
354506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3546f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3547f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3548f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3549f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3550f4ddd8eeSStefano Zampini     }
3551f4ddd8eeSStefano Zampini   }
355206656605SStefano Zampini 
3553f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
355406656605SStefano Zampini     PetscScalar *marray;
355588ebb749SStefano Zampini 
355606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
35578eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
355806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
355988ebb749SStefano Zampini     }
35603301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
356106656605SStefano Zampini       n *= 2;
356288ebb749SStefano Zampini     }
356306656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
356406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
356506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
35668eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
356706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
356806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
356988ebb749SStefano Zampini     }
35703301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
357106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
35728eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
357306656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
357406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
357588ebb749SStefano Zampini       }
357688ebb749SStefano Zampini     } else {
3577c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3578c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
35791b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3580c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3581c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3582c0553b1fSStefano Zampini       }
358388ebb749SStefano Zampini     }
358406656605SStefano Zampini   }
3585019a44ceSStefano Zampini 
358606656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
35874f1b2e48SStefano Zampini   p0_lidx_I = NULL;
35884f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3589d12edf2fSStefano Zampini     const PetscInt *idxs;
3590d12edf2fSStefano Zampini 
3591d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
35924f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
35934f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
35944f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
35954f1b2e48SStefano Zampini     }
3596d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3597d12edf2fSStefano Zampini   }
3598d16cbb6bSStefano Zampini 
359906656605SStefano Zampini   /* vertices */
360006656605SStefano Zampini   if (n_vertices) {
360116f15bc4SStefano Zampini 
3602af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
360304708bb6SStefano Zampini 
360416f15bc4SStefano Zampini     if (n_R) {
360514393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
360606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
360716f15bc4SStefano Zampini       PetscScalar  *x,*y;
360804708bb6SStefano Zampini       PetscBool    isseqaij;
360906656605SStefano Zampini 
361021eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
361114393ed6SStefano Zampini       if (need_benign_correction) {
361214393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
361314393ed6SStefano Zampini         IS                     is_p0;
361414393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
361514393ed6SStefano Zampini 
361614393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
361714393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
361814393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3619af25d912SStefano 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);
362014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
362114393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
362214393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
362314393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
362414393ed6SStefano Zampini       }
362514393ed6SStefano Zampini 
3626ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3627af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3628ffd830a3SStefano Zampini       } else {
3629ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3630ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3631ca92afb2SStefano Zampini         PetscInt       n;
3632ca92afb2SStefano Zampini         PetscBool      flg_row;
3633ffd830a3SStefano Zampini 
3634ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3635ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
36369d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3637ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3638ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3639ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3640ca92afb2SStefano Zampini           PetscInt j;
3641ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3642ffd830a3SStefano Zampini         }
3643ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3644ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3645ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3646ffd830a3SStefano Zampini       }
3647ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3648a3df083aSStefano Zampini       if (need_benign_correction) {
3649df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3650a3df083aSStefano Zampini         PetscScalar        *marr;
3651a3df083aSStefano Zampini 
3652a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
365314393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
365414393ed6SStefano Zampini 
365514393ed6SStefano Zampini                | 0 0  0 | (V)
365614393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
365714393ed6SStefano Zampini                | 0 0 -1 | (p0)
365814393ed6SStefano Zampini 
365914393ed6SStefano Zampini         */
3660df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
366114393ed6SStefano Zampini           const PetscScalar *vals;
366214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
366314393ed6SStefano Zampini           PetscInt          n,j,nz;
366414393ed6SStefano Zampini 
3665df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3666df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
366714393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
366814393ed6SStefano Zampini           for (j=0;j<n;j++) {
366914393ed6SStefano Zampini             PetscScalar val = vals[j];
367014393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
367114393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
367214393ed6SStefano Zampini           }
367314393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3674df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
367514393ed6SStefano Zampini         }
367672b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
367772b8c272SStefano Zampini       }
367872b8c272SStefano Zampini       if (F) {
367914393ed6SStefano Zampini         /* need to correct the rhs */
368072b8c272SStefano Zampini         if (need_benign_correction) {
368172b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
368272b8c272SStefano Zampini           PetscScalar        *marr;
368372b8c272SStefano Zampini 
368472b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
36855cbda25cSStefano Zampini           if (lda_rhs != n_R) {
36865cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
36875cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
36885cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
36895cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
36905cbda25cSStefano Zampini             }
36915cbda25cSStefano Zampini           } else {
3692a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3693a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
36945cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3695a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3696a3df083aSStefano Zampini             }
36975cbda25cSStefano Zampini           }
3698a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3699a3df083aSStefano Zampini         }
370006656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
370114393ed6SStefano Zampini         /* need to correct the solution */
3702a3df083aSStefano Zampini         if (need_benign_correction) {
3703df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3704a3df083aSStefano Zampini           PetscScalar        *marr;
3705a3df083aSStefano Zampini 
3706a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
37075cbda25cSStefano Zampini           if (lda_rhs != n_R) {
37085cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
37095cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
37105cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
37115cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
37125cbda25cSStefano Zampini             }
37135cbda25cSStefano Zampini           } else {
3714a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3715a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
37165cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3717a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3718a3df083aSStefano Zampini             }
37195cbda25cSStefano Zampini           }
3720a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3721a3df083aSStefano Zampini         }
372206656605SStefano Zampini       } else {
372306656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
372406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3725ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3726ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
372706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
372806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
372906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
373006656605SStefano Zampini         }
373106656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
373206656605SStefano Zampini       }
373380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3734ffd830a3SStefano Zampini       /* S_VV and S_CV */
373506656605SStefano Zampini       if (n_constraints) {
373606656605SStefano Zampini         Mat B;
373780677318SStefano Zampini 
3738ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
373980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3740ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3741ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
374280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
374380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
374480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
374580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
374680677318SStefano Zampini         }
3747ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
374880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
374980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3750ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
375180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
375206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3753ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3754ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
375506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
375606656605SStefano Zampini       }
375704708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
375804708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3759511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
376004708bb6SStefano Zampini       }
3761ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3762ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3763ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3764ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3765ffd830a3SStefano Zampini       }
376606656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
376714393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
376814393ed6SStefano Zampini       if (need_benign_correction) {
3769df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
377014393ed6SStefano Zampini         PetscScalar      *marr,*sums;
377114393ed6SStefano Zampini 
377214393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
3773f913dca9SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);CHKERRQ(ierr);
3774df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
377514393ed6SStefano Zampini           const PetscScalar *vals;
377614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
377714393ed6SStefano Zampini           PetscInt          n,j,nz;
377814393ed6SStefano Zampini 
3779df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3780df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
378114393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
378214393ed6SStefano Zampini             PetscInt k;
378314393ed6SStefano Zampini             sums[j] = 0.;
378414393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
378514393ed6SStefano Zampini           }
378614393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
378714393ed6SStefano Zampini           for (j=0;j<n;j++) {
378814393ed6SStefano Zampini             PetscScalar val = vals[j];
378914393ed6SStefano Zampini             PetscInt k;
379014393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
379114393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
379214393ed6SStefano Zampini             }
379314393ed6SStefano Zampini           }
379414393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3795df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
379614393ed6SStefano Zampini         }
379714393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
3798f913dca9SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);CHKERRQ(ierr);
379914393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
380014393ed6SStefano Zampini       }
380180677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
380206656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
380306656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
380406656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
380506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
380606656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
380706656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
380806656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3809d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3810019a44ceSStefano Zampini     } else {
3811d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3812d16cbb6bSStefano Zampini     }
381321eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3814d16cbb6bSStefano Zampini 
381506656605SStefano Zampini     /* coarse basis functions */
381606656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
381716f15bc4SStefano Zampini       PetscScalar *y;
381816f15bc4SStefano Zampini 
3819ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
382006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
382106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
382206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
382306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
382406656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
382506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
382606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
382706656605SStefano Zampini 
382806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
38294f1b2e48SStefano Zampini         PetscInt j;
38304f1b2e48SStefano Zampini 
383106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
383206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
383306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
383406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
383506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
38364f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
383706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
383806656605SStefano Zampini       }
383906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
384006656605SStefano Zampini     }
384104708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
384204708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
384306656605SStefano Zampini   }
38445cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
384506656605SStefano Zampini 
384606656605SStefano Zampini   if (n_constraints) {
384706656605SStefano Zampini     Mat B;
384806656605SStefano Zampini 
3849ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
385006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
385180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
385206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
385306656605SStefano Zampini     if (n_vertices) {
385480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
385580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
385680677318SStefano Zampini       } else {
385780677318SStefano Zampini         Mat S_VCt;
385880677318SStefano Zampini 
3859ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3860ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
386172b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3862ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3863ffd830a3SStefano Zampini         }
386480677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
386580677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
386680677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
386780677318SStefano Zampini       }
386806656605SStefano Zampini     }
386906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
387006656605SStefano Zampini     /* coarse basis functions */
387106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
387206656605SStefano Zampini       PetscScalar *y;
387306656605SStefano Zampini 
3874ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
387506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
387606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
387706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
387806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
387906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
388006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
388106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
38824f1b2e48SStefano Zampini         PetscInt j;
38834f1b2e48SStefano Zampini 
388406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
388506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
388606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
388706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
388806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
38894f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
389006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
389106656605SStefano Zampini       }
389206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
389306656605SStefano Zampini     }
389406656605SStefano Zampini   }
389580677318SStefano Zampini   if (n_constraints) {
389680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
389780677318SStefano Zampini   }
38984f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
389972b8c272SStefano Zampini 
390072b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
390172b8c272SStefano Zampini   if (pcbddc->benign_n) {
390272b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
390372b8c272SStefano Zampini     IS          is_dummy;
390472b8c272SStefano Zampini     PetscScalar *data;
390572b8c272SStefano Zampini     PetscInt    j;
390672b8c272SStefano Zampini 
390772b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
390872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
390972b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
391072b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
391186c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
391272b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
391372b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
391472b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
391572b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
391672b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
391772b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
391872b8c272SStefano Zampini       }
391972b8c272SStefano Zampini     }
392072b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
392172b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
392272b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
392372b8c272SStefano Zampini   }
3924019a44ceSStefano Zampini 
392506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
39263301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3927ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3928ffd830a3SStefano Zampini     PetscScalar *marray;
392906656605SStefano Zampini 
393006656605SStefano Zampini     if (n_constraints) {
3931ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
393206656605SStefano Zampini 
3933af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
393406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3935ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
393616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
393706656605SStefano Zampini       if (n_vertices) {
3938ffd830a3SStefano Zampini         Mat S_VCT;
393906656605SStefano Zampini 
394006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3941ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
394216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
394306656605SStefano Zampini       }
3944ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
39455b782168SStefano Zampini     } else {
39465b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
394706656605SStefano Zampini     }
394816f15bc4SStefano Zampini     if (n_vertices && n_R) {
3949ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3950ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3951ffd830a3SStefano Zampini       PetscInt       n;
3952ffd830a3SStefano Zampini       PetscBool      flg_row;
395306656605SStefano Zampini 
3954ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3955af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3956ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3957ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3958ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3959ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3960ffd830a3SStefano Zampini         PetscInt j;
3961ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3962ffd830a3SStefano Zampini       }
3963ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3964ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3965ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
396606656605SStefano Zampini     }
396706656605SStefano Zampini 
3968ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3969ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3970ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3971ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3972ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
397306656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
397406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
397506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
397606656605SStefano Zampini     }
3977ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
39785b782168SStefano Zampini     if (B_C) {
3979ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3980ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3981ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3982ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3983ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3984ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3985ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
398606656605SStefano Zampini       }
3987ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
39885b782168SStefano Zampini     }
398906656605SStefano Zampini     /* coarse basis functions */
399006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
399106656605SStefano Zampini       PetscScalar *y;
399206656605SStefano Zampini 
3993ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
399406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
399506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
399606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
399706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
399806656605SStefano Zampini       if (i<n_vertices) {
399906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
400006656605SStefano Zampini       }
400106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
400206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
400306656605SStefano Zampini 
400406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
400506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
400606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
400706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
400806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
400906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
401006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
401106656605SStefano Zampini       }
401206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
401306656605SStefano Zampini     }
4014ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
4015ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
401606656605SStefano Zampini   }
4017d62866d3SStefano Zampini   /* free memory */
401888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
401906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
402006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
402106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
402206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
4023d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
4024d62866d3SStefano Zampini   if (n_vertices) {
4025d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
4026d62866d3SStefano Zampini   }
4027d62866d3SStefano Zampini   if (n_constraints) {
4028d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
4029d62866d3SStefano Zampini   }
403088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
403188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
403288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
4033d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
403488ebb749SStefano Zampini     Mat         coarse_sub_mat;
403525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
403688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
403788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
403888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
40398bec7fa6SStefano Zampini     Mat         C_B,CPHI;
40408bec7fa6SStefano Zampini     IS          is_dummy;
40418bec7fa6SStefano Zampini     Vec         mones;
404288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
404388ebb749SStefano Zampini     PetscReal   real_value;
404488ebb749SStefano Zampini 
4045a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
4046a3df083aSStefano Zampini       Mat A;
4047a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
4048a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
4049a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
4050a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
4051a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4052a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
4053a3df083aSStefano Zampini     } else {
405488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
405588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
405688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
405788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
4058a3df083aSStefano Zampini     }
405988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
406088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
4061ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
406288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
406388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
406488ebb749SStefano Zampini     }
406588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
406688ebb749SStefano Zampini 
406725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
40683301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
406925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4070ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
407188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
407288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
407388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
407488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
407588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
407688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
407788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
407888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
407988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
408088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
408188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
408288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
408388ebb749SStefano Zampini     } else {
408488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
408588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
408688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
408788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
408888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
408988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
409088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
409188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
409288ebb749SStefano Zampini     }
409388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
409488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
409588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
4096511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
40974f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4098fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
4099d12edf2fSStefano Zampini       PetscScalar *data,*data2;
41004f1b2e48SStefano Zampini       PetscInt    j;
4101d12edf2fSStefano Zampini 
41024f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
4103fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
4104d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
410586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
4106d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
4107d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
41084f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
41094f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
4110d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
41114f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
41124f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
41134f1b2e48SStefano Zampini         }
4114d12edf2fSStefano Zampini       }
4115d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
4116d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
4117d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
4118d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
4119d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
4120d12edf2fSStefano Zampini     }
4121d12edf2fSStefano Zampini #if 0
4122d12edf2fSStefano Zampini   {
4123d12edf2fSStefano Zampini     PetscViewer viewer;
4124d12edf2fSStefano Zampini     char filename[256];
4125ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4126d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4127d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4128ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
4129ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
4130ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
4131d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
413272b8c272SStefano Zampini     if (save_change) {
413372b8c272SStefano Zampini       Mat phi_B;
413472b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
413572b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
413672b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
413772b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
413872b8c272SStefano Zampini     } else {
4139ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
4140ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
414172b8c272SStefano Zampini     }
4142ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
4143ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
4144ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
4145ffd830a3SStefano Zampini     }
4146ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
4147ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
4148ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
4149ffd830a3SStefano Zampini     }
415072b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
4151ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
4152ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
4153ffd830a3SStefano Zampini     }
4154d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4155d12edf2fSStefano Zampini   }
4156d12edf2fSStefano Zampini #endif
415781d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
41588bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
41591575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
416006656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
41618bec7fa6SStefano Zampini 
41628bec7fa6SStefano Zampini     /* check constraints */
4163a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
4164a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
41654f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
41668bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4167a00504b5SStefano Zampini     } else {
4168a00504b5SStefano Zampini       PetscScalar *data;
4169a00504b5SStefano Zampini       Mat         tmat;
4170a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4171a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
4172a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
4173a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4174a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4175a00504b5SStefano Zampini     }
41768bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
41778bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
41788bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
41798bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4180bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
4181ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
4182bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
4183bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
4184bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
4185bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
4186bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
418788ebb749SStefano Zampini     }
41888bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
41898bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
41908bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
41918bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
419225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
419388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
419488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
419588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
419688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
419788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
419888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
419988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
420088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
420188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
420288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
4203ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
420488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
420588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
420688ebb749SStefano Zampini     }
420788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
420888ebb749SStefano Zampini   }
42098629588bSStefano Zampini   /* get back data */
42108629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
421188ebb749SStefano Zampini   PetscFunctionReturn(0);
421288ebb749SStefano Zampini }
421388ebb749SStefano Zampini 
421488ebb749SStefano Zampini #undef __FUNCT__
4215d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
4216d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
4217aa0d41d4SStefano Zampini {
4218d65f70fdSStefano Zampini   Mat            *work_mat;
4219d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
4220d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
4221c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
4222aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4223aa0d41d4SStefano Zampini 
4224aa0d41d4SStefano Zampini   PetscFunctionBegin;
4225d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
4226d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
4227d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
4228d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
4229aa0d41d4SStefano Zampini 
4230d65f70fdSStefano Zampini   if (!rsorted) {
4231906d46d4SStefano Zampini     const PetscInt *idxs;
4232906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
4233aa0d41d4SStefano Zampini 
4234d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
4235d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
4236d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4237d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
4238aa0d41d4SStefano Zampini     }
4239d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
4240d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
4241d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
4242d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
4243aa0d41d4SStefano Zampini     }
4244d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
4245d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
4246d65f70fdSStefano Zampini   } else {
4247d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
4248d65f70fdSStefano Zampini     isrow_s = isrow;
4249aa0d41d4SStefano Zampini   }
4250906d46d4SStefano Zampini 
4251d65f70fdSStefano Zampini   if (!csorted) {
4252d65f70fdSStefano Zampini     if (isrow == iscol) {
4253d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
4254d65f70fdSStefano Zampini       iscol_s = isrow_s;
4255d65f70fdSStefano Zampini     } else {
4256d65f70fdSStefano Zampini       const PetscInt *idxs;
4257d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
4258906d46d4SStefano Zampini 
4259d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
4260d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
4261d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4262d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
4263d65f70fdSStefano Zampini       }
4264d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
4265d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
4266d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
4267d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
4268d65f70fdSStefano Zampini       }
4269d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
4270d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
4271d65f70fdSStefano Zampini     }
4272d65f70fdSStefano Zampini   } else {
4273d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
4274d65f70fdSStefano Zampini     iscol_s = iscol;
4275d65f70fdSStefano Zampini   }
4276d65f70fdSStefano Zampini 
4277d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4278d65f70fdSStefano Zampini 
4279d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
4280906d46d4SStefano Zampini     Mat      new_mat;
4281d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
4282906d46d4SStefano Zampini 
4283d65f70fdSStefano Zampini     if (!rsorted) {
4284d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
4285d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
4286d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
4287d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
4288906d46d4SStefano Zampini       }
4289d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
4290d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
4291d65f70fdSStefano Zampini     } else {
4292d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
4293906d46d4SStefano Zampini     }
4294d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
4295d65f70fdSStefano Zampini 
4296d65f70fdSStefano Zampini     if (!csorted) {
4297d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
4298d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
4299d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
4300d65f70fdSStefano Zampini       } else {
4301d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
4302f913dca9SStefano Zampini         if (!idxs_perm_c) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present");
4303d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
4304d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
4305d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
4306d65f70fdSStefano Zampini         }
4307d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
4308d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
4309d65f70fdSStefano Zampini       }
4310d65f70fdSStefano Zampini     } else {
4311d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
4312d65f70fdSStefano Zampini     }
4313d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
4314d65f70fdSStefano Zampini 
4315d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
4316d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
4317d65f70fdSStefano Zampini     work_mat[0] = new_mat;
4318d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
4319d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
4320d65f70fdSStefano Zampini   }
4321d65f70fdSStefano Zampini 
4322d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
4323d65f70fdSStefano Zampini   *B = work_mat[0];
4324d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
4325d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
4326d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
4327d65f70fdSStefano Zampini   PetscFunctionReturn(0);
4328d65f70fdSStefano Zampini }
4329d65f70fdSStefano Zampini 
4330d65f70fdSStefano Zampini #undef __FUNCT__
43315e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
43325e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
4333aa0d41d4SStefano Zampini {
4334aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
43355e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4336d65f70fdSStefano Zampini   Mat            new_mat;
43375e8657edSStefano Zampini   IS             is_local,is_global;
4338d65f70fdSStefano Zampini   PetscInt       local_size;
4339d65f70fdSStefano Zampini   PetscBool      isseqaij;
4340aa0d41d4SStefano Zampini   PetscErrorCode ierr;
4341aa0d41d4SStefano Zampini 
4342aa0d41d4SStefano Zampini   PetscFunctionBegin;
4343aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
43445e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
43455e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
4346b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
4347aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
4348d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
4349aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
4350906d46d4SStefano Zampini 
4351906d46d4SStefano Zampini   /* check */
4352906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
4353906d46d4SStefano Zampini     Vec       x,x_change;
4354906d46d4SStefano Zampini     PetscReal error;
4355906d46d4SStefano Zampini 
43565e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
4357906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
43585e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
4359e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4360e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4361d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
436288428137SStefano Zampini     if (!pcbddc->change_interior) {
436388428137SStefano Zampini       const PetscScalar *x,*y,*v;
436488428137SStefano Zampini       PetscReal         lerror = 0.;
436588428137SStefano Zampini       PetscInt          i;
436688428137SStefano Zampini 
436788428137SStefano Zampini       ierr = VecGetArrayRead(matis->x,&x);CHKERRQ(ierr);
436888428137SStefano Zampini       ierr = VecGetArrayRead(matis->y,&y);CHKERRQ(ierr);
436988428137SStefano Zampini       ierr = VecGetArrayRead(matis->counter,&v);CHKERRQ(ierr);
437088428137SStefano Zampini       for (i=0;i<local_size;i++)
437188428137SStefano Zampini         if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror)
437288428137SStefano Zampini           lerror = PetscAbsScalar(x[i]-y[i]);
437388428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->x,&x);CHKERRQ(ierr);
437488428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->y,&y);CHKERRQ(ierr);
437588428137SStefano Zampini       ierr = VecRestoreArrayRead(matis->counter,&v);CHKERRQ(ierr);
437688428137SStefano Zampini       ierr = MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4377637e8532SStefano Zampini       if (error > PETSC_SMALL) {
4378637e8532SStefano Zampini         if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4379637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e\n",error);
4380637e8532SStefano Zampini         } else {
4381637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e\n",error);
4382637e8532SStefano Zampini         }
4383637e8532SStefano Zampini       }
438488428137SStefano Zampini     }
4385e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4386e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4387906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4388906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4389637e8532SStefano Zampini     if (error > PETSC_SMALL) {
4390637e8532SStefano Zampini       if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) {
4391637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
4392637e8532SStefano Zampini       } else {
4393637e8532SStefano Zampini         SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e\n",error);
4394637e8532SStefano Zampini       }
4395637e8532SStefano Zampini     }
4396906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
4397906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4398906d46d4SStefano Zampini   }
4399906d46d4SStefano Zampini 
440022d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
44019b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
440222d5777bSStefano Zampini   if (isseqaij) {
4403a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4404a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
4405aa0d41d4SStefano Zampini   } else {
4406a00504b5SStefano Zampini     Mat work_mat;
44071cf9b237SStefano Zampini 
4408a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4409aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
4410a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
44111d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
4412aa0d41d4SStefano Zampini   }
44133301b35fSStefano Zampini   if (matis->A->symmetric_set) {
44143301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
4415e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
44163301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
4417e496cd5dSStefano Zampini #endif
44183301b35fSStefano Zampini   }
4419d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
4420aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
4421aa0d41d4SStefano Zampini }
4422aa0d41d4SStefano Zampini 
4423aa0d41d4SStefano Zampini #undef __FUNCT__
4424a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
44258ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
4426a64d13efSStefano Zampini {
4427a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
4428a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
4429d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
443053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
44313a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
44323a50541eSStefano Zampini   PetscInt        vbs,bs;
44336816873aSStefano Zampini   PetscBT         bitmask=NULL;
4434a64d13efSStefano Zampini   PetscErrorCode  ierr;
4435a64d13efSStefano Zampini 
4436a64d13efSStefano Zampini   PetscFunctionBegin;
4437b23d619eSStefano Zampini   /*
4438b23d619eSStefano Zampini     No need to setup local scatters if
4439b23d619eSStefano Zampini       - primal space is unchanged
4440b23d619eSStefano Zampini         AND
4441b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4442b23d619eSStefano Zampini         AND
4443b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4444b23d619eSStefano Zampini   */
4445b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4446f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4447f4ddd8eeSStefano Zampini   }
4448f4ddd8eeSStefano Zampini   /* destroy old objects */
4449f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4450f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4451f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4452a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4453b371cd4fSStefano Zampini   n_B = pcis->n_B;
4454b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4455b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
44563a50541eSStefano Zampini 
4457a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
44586816873aSStefano Zampini 
445953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4460b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4461854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4462a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4463a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
44640e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4465a64d13efSStefano Zampini     }
4466a64d13efSStefano Zampini 
4467a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
44684641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
44696816873aSStefano Zampini         idx_R_local[n_R++] = i;
4470a64d13efSStefano Zampini       }
4471a64d13efSStefano Zampini     }
4472df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4473df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
44746816873aSStefano Zampini 
4475df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4476df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
44776816873aSStefano Zampini   }
44783a50541eSStefano Zampini 
44793a50541eSStefano Zampini   /* Block code */
44803a50541eSStefano Zampini   vbs = 1;
44813a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
44823a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
44833a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
44843a50541eSStefano Zampini     PetscInt  *vary;
4485b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4486785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
44873a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4488d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4489d3df7717SStefano 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 */
44900e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4491d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
44923a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
44933a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
44943a50541eSStefano Zampini           break;
44953a50541eSStefano Zampini         }
44963a50541eSStefano Zampini       }
4497d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4498d3df7717SStefano Zampini     } else {
4499d3df7717SStefano Zampini       /* Verify directly the R set */
4500d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4501d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4502d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4503d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4504d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4505d3df7717SStefano Zampini             break;
4506d3df7717SStefano Zampini           }
4507d3df7717SStefano Zampini         }
4508d3df7717SStefano Zampini       }
4509d3df7717SStefano Zampini     }
45103a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
45113a50541eSStefano Zampini       vbs = bs;
45123a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
45133a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
45143a50541eSStefano Zampini       }
45153a50541eSStefano Zampini     }
45163a50541eSStefano Zampini   }
45173a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4518b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4519df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
452053892102SStefano Zampini 
4521df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4522df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
452353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4524df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
452553892102SStefano Zampini   } else {
45263a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
452753892102SStefano Zampini   }
4528a64d13efSStefano Zampini 
4529a64d13efSStefano Zampini   /* print some info if requested */
4530a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4531a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4532a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
45331575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4534a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4535a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
45364f1b2e48SStefano 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);
4537a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4538a64d13efSStefano Zampini   }
4539a64d13efSStefano Zampini 
4540a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4541b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
45426816873aSStefano Zampini     IS       is_aux1,is_aux2;
45436816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
45446816873aSStefano Zampini 
45453a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4546854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4547854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4548a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
45494641a718SStefano Zampini     for (i=0; i<n_D; i++) {
45504641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
45514641a718SStefano Zampini     }
4552a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4553a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
45544641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
45554641a718SStefano Zampini         aux_array1[j++] = i;
4556a64d13efSStefano Zampini       }
4557a64d13efSStefano Zampini     }
4558a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4559a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4560a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
45614641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
45624641a718SStefano Zampini         aux_array2[j++] = i;
4563a64d13efSStefano Zampini       }
4564a64d13efSStefano Zampini     }
4565a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4566a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4567a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4568a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4569a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4570a64d13efSStefano Zampini 
45718eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4572785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4573a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
45744641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
45754641a718SStefano Zampini           aux_array1[j++] = i;
4576a64d13efSStefano Zampini         }
4577a64d13efSStefano Zampini       }
4578a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4579a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4580a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4581a64d13efSStefano Zampini     }
45824641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
45833a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4584d62866d3SStefano Zampini   } else {
4585df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
45866816873aSStefano Zampini     IS                 tis;
45876816873aSStefano Zampini     PetscInt           schur_size;
45886816873aSStefano Zampini 
4589df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
45906816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4591df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
45926816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
45936816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
45946816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
45956816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
45966816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4597d62866d3SStefano Zampini     }
4598d62866d3SStefano Zampini   }
4599a64d13efSStefano Zampini   PetscFunctionReturn(0);
4600a64d13efSStefano Zampini }
4601a64d13efSStefano Zampini 
4602304d26faSStefano Zampini 
4603304d26faSStefano Zampini #undef __FUNCT__
4604304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4605684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4606304d26faSStefano Zampini {
4607304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4608304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4609304d26faSStefano Zampini   PC             pc_temp;
4610304d26faSStefano Zampini   Mat            A_RR;
4611f4ddd8eeSStefano Zampini   MatReuse       reuse;
4612304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4613304d26faSStefano Zampini   PetscReal      value;
461404708bb6SStefano Zampini   PetscInt       n_D,n_R;
4615c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4616304d26faSStefano Zampini   PetscErrorCode ierr;
4617e604994aSStefano Zampini   /* prefixes stuff */
4618312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4619e604994aSStefano Zampini   size_t         len;
4620304d26faSStefano Zampini 
4621304d26faSStefano Zampini   PetscFunctionBegin;
4622304d26faSStefano Zampini 
4623e604994aSStefano Zampini   /* compute prefixes */
4624e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4625e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4626e604994aSStefano Zampini   if (!pcbddc->current_level) {
4627e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4628e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4629e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4630e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4631e604994aSStefano Zampini   } else {
4632e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4633312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4634e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4635e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4636312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4637312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
463834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
463934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4640e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4641e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4642e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4643e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4644e604994aSStefano Zampini   }
4645e604994aSStefano Zampini 
4646304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4647684f6988SStefano Zampini   if (dirichlet) {
4648d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4649450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
46509a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4651450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4652a3df083aSStefano Zampini         Mat    A_IIn;
4653a3df083aSStefano Zampini 
4654a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4655a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4656a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4657a3df083aSStefano Zampini       }
4658450f8f5eSStefano Zampini     }
46593301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
46603301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4661964fefecSStefano Zampini     }
4662ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4663964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4664304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4665304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4666304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4667304d26faSStefano Zampini       /* default */
4668304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4669e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
46709577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4671304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
46729577ea80SStefano Zampini       if (issbaij) {
46739577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
46749577ea80SStefano Zampini       } else {
4675304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
46769577ea80SStefano Zampini       }
4677304d26faSStefano Zampini       /* Allow user's customization */
4678304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4679304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4680304d26faSStefano Zampini     }
4681d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4682b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4683df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4684d62866d3SStefano Zampini 
4685df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4686d5574798SStefano Zampini     }
4687304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4688304d26faSStefano Zampini     if (!n_D) {
4689304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4690304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4691304d26faSStefano Zampini     }
4692304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4693304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4694304d26faSStefano Zampini     /* set ksp_D into pcis data */
4695304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4696304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4697304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4698684f6988SStefano Zampini   }
4699304d26faSStefano Zampini 
4700304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4701684f6988SStefano Zampini   A_RR = 0;
4702684f6988SStefano Zampini   if (neumann) {
4703d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
470404708bb6SStefano Zampini     PetscInt        ibs,mbs;
470504708bb6SStefano Zampini     PetscBool       issbaij;
470604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4707f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
47088ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4709f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4710f4ddd8eeSStefano Zampini       PetscInt nn_R;
471181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4712f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4713f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4714f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4715f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4716f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4717f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4718f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4719727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4720f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4721f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4722f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4723f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4724f4ddd8eeSStefano Zampini         }
4725f4ddd8eeSStefano Zampini       }
4726f4ddd8eeSStefano Zampini       /* last check */
4727d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4728f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4729f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4730f4ddd8eeSStefano Zampini       }
4731f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4732f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4733f4ddd8eeSStefano Zampini     }
4734a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4735af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4736af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
473704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
473804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
473904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
474004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
474104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4742af732b37SStefano Zampini       } else {
4743511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
47446816873aSStefano Zampini       }
474504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
474604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
474704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
474804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
474904708bb6SStefano Zampini       } else {
4750511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
475104708bb6SStefano Zampini       }
475204708bb6SStefano Zampini     }
4753a00504b5SStefano Zampini     /* extract A_RR */
4754b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4755a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4756a00504b5SStefano Zampini 
4757a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
475816e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4759a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
476016e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
476116e386b8SStefano Zampini         } else {
4762a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4763a00504b5SStefano Zampini         }
4764a00504b5SStefano Zampini       } else {
4765a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4766a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4767a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4768a00504b5SStefano Zampini       }
4769a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4770f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
477116e386b8SStefano Zampini     }
47723301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
47733301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
47746816873aSStefano Zampini     }
4775f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4776304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4777304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4778304d26faSStefano Zampini       /* default */
4779304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4780e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4781304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
47829577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
47839577ea80SStefano Zampini       if (issbaij) {
47849577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
47859577ea80SStefano Zampini       } else {
4786304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
47879577ea80SStefano Zampini       }
4788304d26faSStefano Zampini       /* Allow user's customization */
4789304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4790304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4791304d26faSStefano Zampini     }
4792304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4793304d26faSStefano Zampini     if (!n_R) {
4794304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4795304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4796304d26faSStefano Zampini     }
47975cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4798df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4799b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4800df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4801d62866d3SStefano Zampini 
4802df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4803d62866d3SStefano Zampini     }
4804304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4805304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4806684f6988SStefano Zampini   }
4807304d26faSStefano Zampini 
4808684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4809684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
48101575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4811684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4812684f6988SStefano Zampini   }
4813c7017625SStefano Zampini 
4814c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4815c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4816c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4817c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4818c7017625SStefano Zampini   }
4819c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4820c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4821c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4822c7017625SStefano Zampini   }
4823c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4824c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4825c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4826c7017625SStefano Zampini   }
4827c7017625SStefano Zampini 
4828c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4829c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4830684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
48310fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
48320fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
48330fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
48340fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
48350fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4836e604994aSStefano 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);
4837c7017625SStefano Zampini       if (check_corr[0]) {
4838c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4839c7017625SStefano Zampini       }
4840304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4841304d26faSStefano Zampini     }
4842684f6988SStefano Zampini     if (neumann) { /* Neumann */
48430fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
48440fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
48450fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
48460fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
48470fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4848e604994aSStefano 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);
4849c7017625SStefano Zampini       if (check_corr[1]) {
4850c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4851c7017625SStefano Zampini       }
4852304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4853304d26faSStefano Zampini     }
4854684f6988SStefano Zampini   }
48555cbda25cSStefano Zampini   /* free Neumann problem's matrix */
48565cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4857304d26faSStefano Zampini   PetscFunctionReturn(0);
4858304d26faSStefano Zampini }
4859304d26faSStefano Zampini 
4860304d26faSStefano Zampini #undef __FUNCT__
4861ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
486280677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4863674ae819SStefano Zampini {
4864674ae819SStefano Zampini   PetscErrorCode  ierr;
4865674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4866be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4867b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4868674ae819SStefano Zampini 
4869674ae819SStefano Zampini   PetscFunctionBegin;
4870b334f244SStefano Zampini   if (!reuse_solver) {
487180677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
487220c7b377SStefano Zampini   }
487380677318SStefano Zampini   if (!pcbddc->switch_static) {
487480677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
487580677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
487680677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
487720c7b377SStefano Zampini     }
4878b334f244SStefano Zampini     if (!reuse_solver) {
487980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
488080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
488120c7b377SStefano Zampini     } else {
4882df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4883be83ff47SStefano Zampini 
4884df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4885df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
488620c7b377SStefano Zampini     }
4887be83ff47SStefano Zampini   } else {
488880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
488980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
489080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
489180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
489280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
489380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
489480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
489580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
489680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4897674ae819SStefano Zampini     }
4898674ae819SStefano Zampini   }
4899b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
490080677318SStefano Zampini     if (applytranspose) {
490180677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
490280677318SStefano Zampini     } else {
490380677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
490480677318SStefano Zampini     }
4905be83ff47SStefano Zampini   } else {
4906df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4907be83ff47SStefano Zampini 
4908be83ff47SStefano Zampini     if (applytranspose) {
4909df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4910be83ff47SStefano Zampini     } else {
4911df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4912be83ff47SStefano Zampini     }
4913be83ff47SStefano Zampini   }
491480677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
491580677318SStefano Zampini   if (!pcbddc->switch_static) {
4916b334f244SStefano Zampini     if (!reuse_solver) {
491780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
491880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4919be83ff47SStefano Zampini     } else {
4920df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4921be83ff47SStefano Zampini 
4922df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4923df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4924be83ff47SStefano Zampini     }
492580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
492680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
492780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
492880677318SStefano Zampini     }
492980677318SStefano Zampini   } else {
493080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
493180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
493280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
493380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
493480677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
493580677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
493680677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
493780677318SStefano Zampini     }
493880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
493980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
494080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
494180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4942674ae819SStefano Zampini   }
4943674ae819SStefano Zampini   PetscFunctionReturn(0);
4944674ae819SStefano Zampini }
4945674ae819SStefano Zampini 
4946dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4947674ae819SStefano Zampini #undef __FUNCT__
4948674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4949dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4950674ae819SStefano Zampini {
4951674ae819SStefano Zampini   PetscErrorCode ierr;
4952674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4953674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4954674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4955674ae819SStefano Zampini 
4956674ae819SStefano Zampini   PetscFunctionBegin;
4957dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
49584fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4959dc359a40SStefano Zampini     if (applytranspose) {
4960674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
49618eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4962dc359a40SStefano Zampini     } else {
4963674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4964674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
496515aaf578SStefano Zampini     }
49664fee134fSStefano Zampini   } else {
49674fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
49684fee134fSStefano Zampini   }
4969efc2fbd9SStefano Zampini 
4970efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
49714f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4972efc2fbd9SStefano Zampini     PetscScalar *array;
49734f1b2e48SStefano Zampini     PetscInt    j;
4974efc2fbd9SStefano Zampini 
4975efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
49764f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4977efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4978efc2fbd9SStefano Zampini   }
4979efc2fbd9SStefano Zampini 
498012edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
498112edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
498212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
498312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
498412edc857SStefano Zampini 
49859f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
498612edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
498751694757SStefano Zampini     Mat          coarse_mat;
4988964fefecSStefano Zampini     Vec          rhs,sol;
498951694757SStefano Zampini     MatNullSpace nullsp;
499027b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4991964fefecSStefano Zampini 
499227b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
499327b6a85dSStefano Zampini       PC        coarse_pc;
499427b6a85dSStefano Zampini 
499527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
499627b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
499727b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
499827b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
499927b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
500027b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
50013bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
500227b6a85dSStefano Zampini       }
500327b6a85dSStefano Zampini     }
5004964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
5005964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
500651694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
500751694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
500851694757SStefano Zampini     if (nullsp) {
500951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
501051694757SStefano Zampini     }
501112edc857SStefano Zampini     if (applytranspose) {
50129a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
5013964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
50142701bc32SStefano Zampini     } else {
50151f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
50162701bc32SStefano Zampini         PC        coarse_pc;
50172701bc32SStefano Zampini 
50182701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
50192701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
50203e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
50212701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
502212edc857SStefano Zampini       } else {
5023964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
502412edc857SStefano Zampini       }
50252701bc32SStefano Zampini     }
50261d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
502727b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
502827b6a85dSStefano Zampini       PC        coarse_pc;
502927b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
503027b6a85dSStefano Zampini 
503127b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
503227b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
503327b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
50343bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
503527b6a85dSStefano Zampini     }
503651694757SStefano Zampini     if (nullsp) {
503751694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
503851694757SStefano Zampini     }
503912edc857SStefano Zampini   }
5040674ae819SStefano Zampini 
5041674ae819SStefano Zampini   /* Local solution on R nodes */
50424fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
504380677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
50449f00e9b4SStefano Zampini   }
50459f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
50469f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
504712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5048674ae819SStefano Zampini 
50494fee134fSStefano Zampini   /* Sum contributions from the two levels */
50504fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
5051dc359a40SStefano Zampini     if (applytranspose) {
5052dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5053dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5054dc359a40SStefano Zampini     } else {
5055674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
50568eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5057dc359a40SStefano Zampini     }
5058efc2fbd9SStefano Zampini     /* store p0 */
50594f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
5060efc2fbd9SStefano Zampini       PetscScalar *array;
50614f1b2e48SStefano Zampini       PetscInt    j;
5062efc2fbd9SStefano Zampini 
5063efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
50644f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
5065efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5066efc2fbd9SStefano Zampini     }
50674fee134fSStefano Zampini   } else { /* expand the coarse solution */
50684fee134fSStefano Zampini     if (applytranspose) {
50694fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
50704fee134fSStefano Zampini     } else {
50714fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
50724fee134fSStefano Zampini     }
50734fee134fSStefano Zampini   }
5074674ae819SStefano Zampini   PetscFunctionReturn(0);
5075674ae819SStefano Zampini }
5076674ae819SStefano Zampini 
5077674ae819SStefano Zampini #undef __FUNCT__
5078674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
507912edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
5080674ae819SStefano Zampini {
5081674ae819SStefano Zampini   PetscErrorCode ierr;
5082674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
508358da7f69SStefano Zampini   PetscScalar    *array;
508412edc857SStefano Zampini   Vec            from,to;
5085674ae819SStefano Zampini 
5086674ae819SStefano Zampini   PetscFunctionBegin;
508712edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
508812edc857SStefano Zampini     from = pcbddc->coarse_vec;
508912edc857SStefano Zampini     to = pcbddc->vec1_P;
509012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
509112edc857SStefano Zampini       Vec tvec;
509258da7f69SStefano Zampini 
509358da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
509458da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
509512edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
509658da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
509758da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
509858da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
509912edc857SStefano Zampini     }
510012edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
510112edc857SStefano Zampini     from = pcbddc->vec1_P;
510212edc857SStefano Zampini     to = pcbddc->coarse_vec;
510312edc857SStefano Zampini   }
510412edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
5105674ae819SStefano Zampini   PetscFunctionReturn(0);
5106674ae819SStefano Zampini }
5107674ae819SStefano Zampini 
5108674ae819SStefano Zampini #undef __FUNCT__
5109674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
511012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
5111674ae819SStefano Zampini {
5112674ae819SStefano Zampini   PetscErrorCode ierr;
5113674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
511458da7f69SStefano Zampini   PetscScalar    *array;
511512edc857SStefano Zampini   Vec            from,to;
5116674ae819SStefano Zampini 
5117674ae819SStefano Zampini   PetscFunctionBegin;
511812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
511912edc857SStefano Zampini     from = pcbddc->coarse_vec;
512012edc857SStefano Zampini     to = pcbddc->vec1_P;
512112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
512212edc857SStefano Zampini     from = pcbddc->vec1_P;
512312edc857SStefano Zampini     to = pcbddc->coarse_vec;
512412edc857SStefano Zampini   }
512512edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
512612edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
512712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
512812edc857SStefano Zampini       Vec tvec;
512958da7f69SStefano Zampini 
513012edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
513158da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
513258da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
513358da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
513458da7f69SStefano Zampini     }
513558da7f69SStefano Zampini   } else {
513658da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
513758da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
513812edc857SStefano Zampini     }
513912edc857SStefano Zampini   }
5140674ae819SStefano Zampini   PetscFunctionReturn(0);
5141674ae819SStefano Zampini }
5142674ae819SStefano Zampini 
5143984c4197SStefano Zampini /* uncomment for testing purposes */
5144984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
5145674ae819SStefano Zampini #undef __FUNCT__
5146674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
5147674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
5148674ae819SStefano Zampini {
5149674ae819SStefano Zampini   PetscErrorCode    ierr;
5150674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
5151674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
5152674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
5153984c4197SStefano Zampini   /* one and zero */
5154984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
5155984c4197SStefano Zampini   /* space to store constraints and their local indices */
51569162d606SStefano Zampini   PetscScalar       *constraints_data;
51579162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
51589162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
51599162d606SStefano Zampini   PetscInt          *constraints_n;
5160984c4197SStefano Zampini   /* iterators */
5161b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
5162984c4197SStefano Zampini   /* BLAS integers */
5163e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
5164e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
5165c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
5166727cdba6SStefano Zampini   /* reuse */
51670e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
51680e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
5169984c4197SStefano Zampini   /* change of basis */
5170b3d85658SStefano Zampini   PetscBool         qr_needed;
51719162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
5172984c4197SStefano Zampini   /* auxiliary stuff */
517364efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
51748a0068c3SStefano Zampini   PetscInt          ncc;
5175984c4197SStefano Zampini   /* some quantities */
517645a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
5177a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
5178984c4197SStefano Zampini 
5179674ae819SStefano Zampini   PetscFunctionBegin;
51808e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
51818e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
51828e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
518316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
5184088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
5185088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
51860e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
51870e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
51880e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
51890e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
51900e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
5191088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5192cf5a6209SStefano Zampini 
5193cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
51949162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
5195cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
5196cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
5197cf5a6209SStefano Zampini     Vec          *localnearnullsp;
5198cf5a6209SStefano Zampini     PetscScalar  *array;
5199cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
5200cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
5201674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
5202b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
5203674ae819SStefano Zampini     PetscScalar  *work;
5204674ae819SStefano Zampini     PetscReal    *singular_vals;
5205674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5206674ae819SStefano Zampini     PetscReal    *rwork;
5207674ae819SStefano Zampini #endif
5208674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5209674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
5210674ae819SStefano Zampini #else
5211964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
5212964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
5213674ae819SStefano Zampini #endif
5214674ae819SStefano Zampini 
5215674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
5216d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
5217e4d548c7SStefano Zampini     /* print some info */
52185c643e28SStefano Zampini     if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) {
5219e4d548c7SStefano Zampini       PetscInt nv;
5220e4d548c7SStefano Zampini 
5221c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5222e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
5223e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5224e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5225e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
5226e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
5227e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
5228e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5229e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
5230e4d548c7SStefano Zampini     }
5231e4d548c7SStefano Zampini 
5232d06fc5fdSStefano Zampini     /* free unneeded index sets */
5233d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
5234d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
5235674ae819SStefano Zampini     }
5236d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
5237d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
5238d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5239d06fc5fdSStefano Zampini       }
5240d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5241d06fc5fdSStefano Zampini       n_ISForEdges = 0;
5242d06fc5fdSStefano Zampini     }
5243d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
5244d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
5245d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5246d06fc5fdSStefano Zampini       }
5247d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5248d06fc5fdSStefano Zampini       n_ISForFaces = 0;
5249d06fc5fdSStefano Zampini     }
525070022509SStefano Zampini 
5251674ae819SStefano Zampini     /* check if near null space is attached to global mat */
5252674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
5253674ae819SStefano Zampini     if (nearnullsp) {
5254674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
5255f4ddd8eeSStefano Zampini       /* remove any stored info */
5256f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
5257f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5258f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
5259f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
5260f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
5261473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
5262f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
5263f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
5264f4ddd8eeSStefano Zampini       }
5265984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
5266984c4197SStefano Zampini       nnsp_size = 0;
5267674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
5268674ae819SStefano Zampini     }
5269984c4197SStefano Zampini     /* get max number of constraints on a single cc */
5270984c4197SStefano Zampini     max_constraints = nnsp_size;
5271984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
5272984c4197SStefano Zampini 
5273674ae819SStefano Zampini     /*
5274674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
52759162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
52769162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
52779162d606SStefano Zampini          There can be multiple constraints per connected component
5278674ae819SStefano Zampini                                                                                                                                                            */
5279674ae819SStefano Zampini     n_vertices = 0;
5280674ae819SStefano Zampini     if (ISForVertices) {
5281674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
5282674ae819SStefano Zampini     }
52839162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
52849162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
52859162d606SStefano Zampini 
52869162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
52879162d606SStefano Zampini     total_counts *= max_constraints;
5288674ae819SStefano Zampini     total_counts += n_vertices;
52894641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
52909162d606SStefano Zampini 
5291674ae819SStefano Zampini     total_counts = 0;
5292674ae819SStefano Zampini     max_size_of_constraint = 0;
5293674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
52949162d606SStefano Zampini       IS used_is;
5295674ae819SStefano Zampini       if (i<n_ISForEdges) {
52969162d606SStefano Zampini         used_is = ISForEdges[i];
5297674ae819SStefano Zampini       } else {
52989162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
5299674ae819SStefano Zampini       }
53009162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
5301674ae819SStefano Zampini       total_counts += j;
5302674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
5303674ae819SStefano Zampini     }
53049162d606SStefano 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);
53059162d606SStefano Zampini 
5306984c4197SStefano Zampini     /* get local part of global near null space vectors */
5307785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
5308984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5309984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
5310e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5311e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5312984c4197SStefano Zampini     }
5313674ae819SStefano Zampini 
5314242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
5315242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
5316a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
5317242a89d7SStefano Zampini 
5318984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
5319a773dcb8SStefano Zampini     if (!skip_lapack) {
5320674ae819SStefano Zampini       PetscScalar temp_work;
5321911cabfeSStefano Zampini 
5322674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5323984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
5324785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
5325785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
5326785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
5327674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5328785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
5329674ae819SStefano Zampini #endif
5330674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5331c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
5332c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
5333674ae819SStefano Zampini       lwork = -1;
5334674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5335674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5336c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
5337674ae819SStefano Zampini #else
5338c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
5339674ae819SStefano Zampini #endif
5340674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5341984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
5342674ae819SStefano Zampini #else /* on missing GESVD */
5343674ae819SStefano Zampini       /* SVD */
5344674ae819SStefano Zampini       PetscInt max_n,min_n;
5345674ae819SStefano Zampini       max_n = max_size_of_constraint;
5346984c4197SStefano Zampini       min_n = max_constraints;
5347984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
5348674ae819SStefano Zampini         min_n = max_size_of_constraint;
5349984c4197SStefano Zampini         max_n = max_constraints;
5350674ae819SStefano Zampini       }
5351785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
5352674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5353785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
5354674ae819SStefano Zampini #endif
5355674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
5356674ae819SStefano Zampini       lwork = -1;
5357e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
5358e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
5359b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
5360674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5361674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
53629162d606SStefano 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));
5363674ae819SStefano Zampini #else
53649162d606SStefano 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));
5365674ae819SStefano Zampini #endif
5366674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
5367984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
5368984c4197SStefano Zampini #endif /* on missing GESVD */
5369674ae819SStefano Zampini       /* Allocate optimal workspace */
5370674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
5371854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
5372674ae819SStefano Zampini     }
5373674ae819SStefano Zampini     /* Now we can loop on constraining sets */
5374674ae819SStefano Zampini     total_counts = 0;
53759162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
53769162d606SStefano Zampini     constraints_data_ptr[0] = 0;
5377674ae819SStefano Zampini     /* vertices */
53789162d606SStefano Zampini     if (n_vertices) {
5379674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
53809162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
5381674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
53829162d606SStefano Zampini         constraints_n[total_counts] = 1;
53839162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
53849162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
53859162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
5386674ae819SStefano Zampini         total_counts++;
5387674ae819SStefano Zampini       }
5388674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5389674ae819SStefano Zampini       n_vertices = total_counts;
5390674ae819SStefano Zampini     }
5391984c4197SStefano Zampini 
5392674ae819SStefano Zampini     /* edges and faces */
53939162d606SStefano Zampini     total_counts_cc = total_counts;
5394911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
53959162d606SStefano Zampini       IS        used_is;
53969162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
53979162d606SStefano Zampini 
5398911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
53999162d606SStefano Zampini         used_is = ISForEdges[ncc];
5400984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
5401674ae819SStefano Zampini       } else {
54029162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
5403984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
5404674ae819SStefano Zampini       }
5405674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
54069162d606SStefano Zampini 
54079162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
54089162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5409984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
5410984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
5411674ae819SStefano Zampini       if (nnsp_has_cnst) {
54125b08dc53SStefano Zampini         PetscScalar quad_value;
54139162d606SStefano Zampini 
54149162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
54159162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
54169162d606SStefano Zampini 
5417a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
5418674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
5419a773dcb8SStefano Zampini         } else {
5420a773dcb8SStefano Zampini           quad_value = 1.0;
5421a773dcb8SStefano Zampini         }
5422674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
54239162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
5424674ae819SStefano Zampini         }
54259162d606SStefano Zampini         temp_constraints++;
5426674ae819SStefano Zampini         total_counts++;
5427674ae819SStefano Zampini       }
5428674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
5429984c4197SStefano Zampini         PetscReal real_value;
54309162d606SStefano Zampini         PetscScalar *ptr_to_data;
54319162d606SStefano Zampini 
5432984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
54339162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
5434674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
54359162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
5436674ae819SStefano Zampini         }
5437984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5438984c4197SStefano Zampini         /* check if array is null on the connected component */
5439e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54409162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
54415b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5442674ae819SStefano Zampini           temp_constraints++;
5443674ae819SStefano Zampini           total_counts++;
54449162d606SStefano Zampini           if (!idxs_copied) {
54459162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
54469162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5447674ae819SStefano Zampini           }
5448674ae819SStefano Zampini         }
54499162d606SStefano Zampini       }
54509162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
545145a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5452eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5453a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
54549162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
54559162d606SStefano Zampini 
54569162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5457a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54589162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5459a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
54609162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5461a773dcb8SStefano Zampini         } else { /* perform SVD */
5462984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
54639162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5464674ae819SStefano Zampini 
5465674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5466984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5467984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5468984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5469984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5470984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5471984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5472984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5473984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5474674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5475e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5476984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5477674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5478674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
54799162d606SStefano 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));
5480674ae819SStefano Zampini             }
5481674ae819SStefano Zampini           }
5482e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5483e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5484e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5485674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5486c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5487674ae819SStefano Zampini #else
5488c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5489674ae819SStefano Zampini #endif
5490674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5491984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5492984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5493674ae819SStefano Zampini           j = 0;
5494984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5495674ae819SStefano Zampini           total_counts = total_counts-j;
549645a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5497e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5498c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5499c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5500c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5501c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5502c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5503c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5504674ae819SStefano Zampini           if (j<temp_constraints) {
5505984c4197SStefano Zampini             PetscInt ii;
5506984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5507674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
55089162d606SStefano 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));
5509674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5510984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5511674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
55129162d606SStefano 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];
5513674ae819SStefano Zampini               }
5514674ae819SStefano Zampini             }
5515674ae819SStefano Zampini           }
5516674ae819SStefano Zampini #else  /* on missing GESVD */
5517e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5518e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5519b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5520674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5521674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
55229162d606SStefano 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));
5523674ae819SStefano Zampini #else
55249162d606SStefano 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));
5525674ae819SStefano Zampini #endif
5526984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5527674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5528984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5529e310c8b4SStefano Zampini           k = temp_constraints;
5530e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5531674ae819SStefano Zampini           j = 0;
5532e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
553345a1bb75SStefano Zampini           valid_constraints = k-j;
5534911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5535984c4197SStefano Zampini #endif /* on missing GESVD */
5536674ae819SStefano Zampini         }
5537a773dcb8SStefano Zampini       }
55389162d606SStefano Zampini       /* update pointers information */
55399162d606SStefano Zampini       if (valid_constraints) {
55409162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
55419162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
55429162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
55439162d606SStefano Zampini         /* set change_of_basis flag */
554445a1bb75SStefano Zampini         if (boolforchange) {
5545b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
55469162d606SStefano Zampini         }
5547b3d85658SStefano Zampini         total_counts_cc++;
554845a1bb75SStefano Zampini       }
554945a1bb75SStefano Zampini     }
5550984c4197SStefano Zampini     /* free workspace */
55518f1c130eSStefano Zampini     if (!skip_lapack) {
5552984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5553984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5554984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5555984c4197SStefano Zampini #endif
5556984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5557984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5558984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5559984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5560984c4197SStefano Zampini #endif
5561984c4197SStefano Zampini     }
5562984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5563984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5564984c4197SStefano Zampini     }
5565984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5566cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5567cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5568cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5569cf5a6209SStefano Zampini     }
5570cf5a6209SStefano Zampini     if (n_ISForFaces) {
5571cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5572cf5a6209SStefano Zampini     }
5573cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5574cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5575cf5a6209SStefano Zampini     }
5576cf5a6209SStefano Zampini     if (n_ISForEdges) {
5577cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5578cf5a6209SStefano Zampini     }
5579cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
558008122e43SStefano Zampini   } else {
558108122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5582984c4197SStefano Zampini 
558308122e43SStefano Zampini     total_counts = 0;
558408122e43SStefano Zampini     n_vertices = 0;
5585d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5586d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
558708122e43SStefano Zampini     }
558808122e43SStefano Zampini     max_constraints = 0;
55899162d606SStefano Zampini     total_counts_cc = 0;
559008122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
559108122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
55929162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
559308122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
559408122e43SStefano Zampini     }
55959162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
55969162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
55979162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
55989162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
559974d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
56009162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
56019162d606SStefano Zampini     total_counts_cc = 0;
56029162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
56039162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
56049162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
560508122e43SStefano Zampini       }
560608122e43SStefano Zampini     }
56079162d606SStefano Zampini #if 0
56089162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
56099162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
56109162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
56119162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
56129162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
56139162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
56149162d606SStefano Zampini       }
56159162d606SStefano Zampini       printf("\n");
56169162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
56179162d606SStefano Zampini     }
56181b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
56198bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
56201b968477SStefano Zampini     }
56211b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
56228bec7fa6SStefano 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]);
56231b968477SStefano Zampini     }
562408122e43SStefano Zampini #endif
562508122e43SStefano Zampini 
56268bec7fa6SStefano Zampini     max_size_of_constraint = 0;
56279162d606SStefano 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]);
56289162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
562908122e43SStefano Zampini     /* Change of basis */
5630b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
563108122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
563208122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
563308122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5634b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
563508122e43SStefano Zampini         }
563608122e43SStefano Zampini       }
563708122e43SStefano Zampini     }
563808122e43SStefano Zampini   }
5639984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
56404f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
564108122e43SStefano Zampini 
56429162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
56439162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
5644eee23b56SStefano 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);
5645674ae819SStefano Zampini 
5646674ae819SStefano Zampini   /* Create constraint matrix */
5647674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
564816f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5649984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5650984c4197SStefano Zampini 
5651984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5652a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5653a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
565474d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5655984c4197SStefano Zampini   total_primal_vertices=0;
5656b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
56579162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
56589162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
565972b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
56609162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5661b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
566264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
56639162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
56649162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5665a717540cSStefano Zampini       }
5666b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
566791af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5668a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5669a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5670a717540cSStefano Zampini       }
5671fa434743SStefano Zampini     } else {
5672b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5673fa434743SStefano Zampini     }
5674a717540cSStefano Zampini   }
5675b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5676b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5677674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
567870022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
56794f1b2e48SStefano 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);
56800e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
56810e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5682984c4197SStefano Zampini 
5683984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
568474d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5685785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5686984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
568774d5cdf7SStefano Zampini 
5688984c4197SStefano Zampini   j = total_primal_vertices;
568974d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5690b3d85658SStefano Zampini   cum = total_primal_vertices;
56919162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
56924641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5693b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5694b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5695b3d85658SStefano Zampini       cum++;
56969162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
569774d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
569874d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
569974d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
570074d5cdf7SStefano Zampini       }
57019162d606SStefano Zampini       j += constraints_n[i];
5702674ae819SStefano Zampini     }
5703674ae819SStefano Zampini   }
5704674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5705674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5706088faed8SStefano Zampini 
5707674ae819SStefano Zampini   /* set values in constraint matrix */
5708984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
57090e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5710674ae819SStefano Zampini   }
5711984c4197SStefano Zampini   total_counts = total_primal_vertices;
57129162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
57134641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
57149162d606SStefano Zampini       PetscInt *cols;
57159162d606SStefano Zampini 
57169162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
57179162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
57189162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
57199162d606SStefano Zampini         PetscInt    row = total_counts+k;
57209162d606SStefano Zampini         PetscScalar *vals;
57219162d606SStefano Zampini 
57229162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
57239162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
57249162d606SStefano Zampini       }
57259162d606SStefano Zampini       total_counts += constraints_n[i];
5726674ae819SStefano Zampini     }
5727674ae819SStefano Zampini   }
5728674ae819SStefano Zampini   /* assembling */
5729674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5730674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5731088faed8SStefano Zampini 
5732984c4197SStefano Zampini   /*
57336a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5734984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5735f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5736984c4197SStefano Zampini   */
5737674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5738674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5739026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5740984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5741984c4197SStefano Zampini     /* working stuff for GEQRF */
574281d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5743984c4197SStefano Zampini     PetscBLASInt lqr_work;
5744984c4197SStefano Zampini     /* working stuff for UNGQR */
5745984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5746984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5747984c4197SStefano Zampini     /* working stuff for TRTRS */
5748984c4197SStefano Zampini     PetscScalar  *trs_rhs;
57493f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5750984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5751984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5752984c4197SStefano Zampini     PetscScalar  *start_vals;
5753984c4197SStefano Zampini     /* working stuff for values insertion */
57544641a718SStefano Zampini     PetscBT      is_primal;
575564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5756906d46d4SStefano Zampini     /* matrix sizes */
5757906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5758906d46d4SStefano Zampini     /* temporary change of basis */
5759906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5760cf5a6209SStefano Zampini     /* extra space for debugging */
5761cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5762984c4197SStefano Zampini 
5763906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5764906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
576516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5766bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5767906d46d4SStefano Zampini     /* nonzeros for local mat */
5768bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
57691dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5770bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
57711dd7afcfSStefano Zampini     } else {
57721dd7afcfSStefano Zampini       const PetscInt *ii;
57731dd7afcfSStefano Zampini       PetscInt       n;
57741dd7afcfSStefano Zampini       PetscBool      flg_row;
57751dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
57761dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
57771dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
57781dd7afcfSStefano Zampini     }
57799162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5780a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
57819162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5782a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
57839162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5784a717540cSStefano Zampini         } else {
57859162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
57869162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5787a717540cSStefano Zampini         }
5788a717540cSStefano Zampini       }
5789a717540cSStefano Zampini     }
5790906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5791bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
57921dd7afcfSStefano Zampini     /* Set interior change in the matrix */
57931dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5794bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5795906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5796a717540cSStefano Zampini       }
57971dd7afcfSStefano Zampini     } else {
57981dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
57991dd7afcfSStefano Zampini       PetscScalar    *aa;
58001dd7afcfSStefano Zampini       PetscInt       n;
58011dd7afcfSStefano Zampini       PetscBool      flg_row;
58021dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
58031dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
58041dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
58051dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
58061dd7afcfSStefano Zampini       }
58071dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
58081dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
58091dd7afcfSStefano Zampini     }
5810a717540cSStefano Zampini 
5811a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5812a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5813a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5814a717540cSStefano Zampini     }
5815a717540cSStefano Zampini 
5816a717540cSStefano Zampini 
5817a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5818a717540cSStefano Zampini     /*
5819a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5820a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5821a717540cSStefano Zampini 
5822a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5823a717540cSStefano Zampini 
5824a6b551f4SStefano 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)
5825a6b551f4SStefano Zampini 
5826a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5827a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5828a717540cSStefano Zampini             |              ...                        |
5829a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5830a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5831a717540cSStefano Zampini 
5832a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5833a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5834a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5835a6b551f4SStefano Zampini 
5836a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5837a717540cSStefano Zampini     */
5838a717540cSStefano Zampini     if (qr_needed) {
5839984c4197SStefano Zampini       /* space to store Q */
5840854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
58414e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
58424e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5843984c4197SStefano Zampini       /* first we issue queries for optimal work */
58443f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
58453f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
58463f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5847984c4197SStefano Zampini       lqr_work = -1;
58483f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5849984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5850984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5851785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5852984c4197SStefano Zampini       lgqr_work = -1;
58533f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
58543f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
58553f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
58563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
58573f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
58583f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5859984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5860984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5861785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5862984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5863785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5864a717540cSStefano Zampini       /* allocating workspace for check */
5865a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5866cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5867a717540cSStefano Zampini       }
5868a717540cSStefano Zampini     }
5869984c4197SStefano Zampini     /* array to store whether a node is primal or not */
58704641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5871473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
58720e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
5873eee23b56SStefano 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);
587439e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
587539e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
587639e2fb2aSStefano Zampini     }
587739e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5878984c4197SStefano Zampini 
5879a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
58809162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
58819162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
58824641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5883984c4197SStefano Zampini         /* get constraint info */
58849162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5885984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5886984c4197SStefano Zampini 
5887984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
58889162d606SStefano 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);
5889674ae819SStefano Zampini         }
5890984c4197SStefano Zampini 
5891fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5892a717540cSStefano Zampini 
5893a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5894a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
58959162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5896a717540cSStefano Zampini           }
5897984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
58989162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5899984c4197SStefano Zampini 
5900984c4197SStefano Zampini           /* compute QR decomposition of constraints */
59013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
59023f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
59033f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5904674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
59053f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5906984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5907674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5908984c4197SStefano Zampini 
5909984c4197SStefano Zampini           /* explictly compute R^-T */
5910984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5911984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
59123f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
59133f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
59143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
59153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5916984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
59173f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5918984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5919984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5920984c4197SStefano Zampini 
5921a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
59223f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
59233f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
59243f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
59253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5926984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
59273f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5928984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5929984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5930984c4197SStefano Zampini 
5931984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5932984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5933984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
59343f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
59353f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
59363f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
59373f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
59383f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
59393f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5940984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
59419162d606SStefano 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));
5942984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
59439162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5944984c4197SStefano Zampini 
5945984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
59469162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5947984c4197SStefano Zampini           /* insert cols for primal dofs */
5948984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5949984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
59509162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5951906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5952984c4197SStefano Zampini           }
5953984c4197SStefano Zampini           /* insert cols for dual dofs */
5954984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
59559162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5956984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
59579162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5958906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5959984c4197SStefano Zampini               j++;
5960674ae819SStefano Zampini             }
5961674ae819SStefano Zampini           }
5962984c4197SStefano Zampini 
5963984c4197SStefano Zampini           /* check change of basis */
5964984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5965984c4197SStefano Zampini             PetscInt   ii,jj;
5966984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5967c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5968c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5969c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5970c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5971c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5972c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5973984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5974cf5a6209SStefano 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));
5975984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5976984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5977984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5978cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5979cf5a6209SStefano 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;
5980674ae819SStefano Zampini               }
5981674ae819SStefano Zampini             }
5982984c4197SStefano Zampini             if (!valid_qr) {
598322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5984984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5985984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5986cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5987cf5a6209SStefano 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]));
5988674ae819SStefano Zampini                   }
5989cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5990cf5a6209SStefano 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]));
5991984c4197SStefano Zampini                   }
5992984c4197SStefano Zampini                 }
5993984c4197SStefano Zampini               }
5994674ae819SStefano Zampini             } else {
599522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5996674ae819SStefano Zampini             }
5997674ae819SStefano Zampini           }
5998a717540cSStefano Zampini         } else { /* simple transformation block */
5999a717540cSStefano Zampini           PetscInt    row,col;
6000a6b551f4SStefano Zampini           PetscScalar val,norm;
6001a6b551f4SStefano Zampini 
6002a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
60039162d606SStefano 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));
6004a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
60059162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
60069162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
6007bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
60089162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
6009906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
60109162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
6011a717540cSStefano Zampini             } else {
6012a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
60139162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
6014a717540cSStefano Zampini                 if (row != col) {
60159162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
6016a717540cSStefano Zampini                 } else {
60179162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
6018a717540cSStefano Zampini                 }
6019906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
6020a717540cSStefano Zampini               }
6021a717540cSStefano Zampini             }
6022a717540cSStefano Zampini           }
602398a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
602422d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
6025a717540cSStefano Zampini           }
6026674ae819SStefano Zampini         }
6027984c4197SStefano Zampini       } else {
6028984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
60299162d606SStefano 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);
6030674ae819SStefano Zampini         }
6031674ae819SStefano Zampini       }
6032674ae819SStefano Zampini     }
6033a717540cSStefano Zampini 
6034a717540cSStefano Zampini     /* free workspace */
6035a717540cSStefano Zampini     if (qr_needed) {
6036984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
6037cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
6038984c4197SStefano Zampini       }
6039984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
6040984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
6041984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
6042984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
6043984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
6044674ae819SStefano Zampini     }
6045a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
6046906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6047906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6048906d46d4SStefano Zampini 
6049906d46d4SStefano Zampini     /* assembling of global change of variable */
605088c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
6051bbb9e6c6SStefano Zampini       Mat      tmat;
605216f15bc4SStefano Zampini       PetscInt bs;
605316f15bc4SStefano Zampini 
6054906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
6055906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
6056bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
6057bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
6058bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6059bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
606016f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
606116f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
6062906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
6063bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
6064bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
6065bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6066bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6067bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6068e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6069e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6070bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
6071bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
607288c03ad3SStefano Zampini 
6073906d46d4SStefano Zampini       /* check */
6074906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
6075906d46d4SStefano Zampini         PetscReal error;
6076906d46d4SStefano Zampini         Vec       x,x_change;
6077906d46d4SStefano Zampini 
6078906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
6079906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
6080906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
6081906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
6082e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6083e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6084bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
6085e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6086e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6087906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
6088906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
6089906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
6090637e8532SStefano Zampini         if (error > PETSC_SMALL) {
6091637e8532SStefano Zampini           SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e\n",error);
6092637e8532SStefano Zampini         }
6093906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
6094906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
6095906d46d4SStefano Zampini       }
6096b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
6097b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
6098b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
6099bf3a8328SStefano Zampini 
61009a962809SStefano 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);
6101b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
6102ac632422SStefano Zampini           Mat                    S_new,tmat;
6103bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
6104bbb9e6c6SStefano Zampini 
6105bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
61066816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
6107bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6108bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
6109bf3a8328SStefano Zampini             IS                     is_V;
6110b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
6111b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
6112b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
6113b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
6114b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
6115bf3a8328SStefano Zampini           }
6116bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
6117ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6118b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
6119ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6120bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
6121bf3a8328SStefano Zampini             const PetscScalar *array;
6122bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
6123bf3a8328SStefano Zampini             PetscInt          i,n_V;
6124bf3a8328SStefano Zampini 
6125b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6126b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
6127b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6128b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6129b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
6130b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
6131b087196eSStefano Zampini               PetscScalar val;
6132b087196eSStefano Zampini               PetscInt    idx;
6133b087196eSStefano Zampini 
6134b087196eSStefano Zampini               idx = idxs_V[i];
6135b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
6136b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
6137b087196eSStefano Zampini             }
6138b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6139b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6140bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
6141bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
6142bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
6143bf3a8328SStefano Zampini           }
6144ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
6145ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6146ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
6147ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
6148b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
6149ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
6150bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
6151b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
6152bf3a8328SStefano Zampini             }
6153ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
6154ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
6155ac632422SStefano Zampini           }
6156b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
615788c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
6158b96c3477SStefano Zampini         }
6159c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
6160b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
6161c9db6a07SStefano Zampini           PetscInt i;
6162c9db6a07SStefano Zampini 
6163c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
6164c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
6165c9db6a07SStefano Zampini           }
6166c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
6167c9db6a07SStefano Zampini         }
6168b96c3477SStefano Zampini       }
616916909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
617016909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
617116909a7fSStefano Zampini       } else {
6172906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
617316909a7fSStefano Zampini       }
61741dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
617527b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
617672b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
617772b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
617872b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
617972b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
618072b8c272SStefano Zampini     }
61811dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
618227b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
6183b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
6184b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
6185906d46d4SStefano Zampini     } else {
61861dd7afcfSStefano Zampini       Mat benign_global = NULL;
618727b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
61881dd7afcfSStefano Zampini         Mat tmat;
61891dd7afcfSStefano Zampini 
61901dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
61911dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
61921dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
61931dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
61941dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
61951dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
61961dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
61971dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
61981dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
61991dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
62001dd7afcfSStefano Zampini           Mat M;
62011dd7afcfSStefano Zampini 
62021dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
62031dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
62041dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
62051dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
6206906d46d4SStefano Zampini         } else {
62071dd7afcfSStefano Zampini           Mat         eye;
62081dd7afcfSStefano Zampini           PetscScalar *array;
62091dd7afcfSStefano Zampini 
62101dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
62111dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
62121dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
62131dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
6214906d46d4SStefano Zampini           }
62151dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
62161dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
62171dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
62181dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
62191dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
62201dd7afcfSStefano Zampini         }
62211dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
62221dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
62231dd7afcfSStefano Zampini       }
62241dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
62251dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
62261dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
622727b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
62281dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
62291dd7afcfSStefano Zampini       }
62301dd7afcfSStefano Zampini     }
623116909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
623216909a7fSStefano Zampini       IS             is_global;
623316909a7fSStefano Zampini       const PetscInt *gidxs;
623416909a7fSStefano Zampini 
623516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
623616909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
623716909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
623816909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
623916909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
624016909a7fSStefano Zampini     }
62411dd7afcfSStefano Zampini   }
62421dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
62431dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
6244b9b85e73SStefano Zampini   }
6245a717540cSStefano Zampini 
624672b8c272SStefano Zampini   if (!pcbddc->fake_change) {
62474f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
62484f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
62494f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
62504f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
6251019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
6252019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
6253019a44ceSStefano Zampini       pcbddc->local_primal_size++;
6254019a44ceSStefano Zampini     }
6255019a44ceSStefano Zampini 
6256019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
6257727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
6258727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
62599f47a83aSStefano 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);
6260c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
62610e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
62629f47a83aSStefano 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);
6263727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
6264727cdba6SStefano Zampini       }
62650e6343abSStefano Zampini     }
6266727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
6267b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
626872b8c272SStefano Zampini   }
626972b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
6270727cdba6SStefano Zampini 
6271a717540cSStefano Zampini   /* flush dbg viewer */
6272b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
6273b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6274b8ffe317SStefano Zampini   }
6275a717540cSStefano Zampini 
6276e310c8b4SStefano Zampini   /* free workspace */
6277a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
62784641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
627908122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
62809162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
62819162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
628208122e43SStefano Zampini   } else {
62839162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
62849162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
62859162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
628608122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
628708122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
62889162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
62899162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
629008122e43SStefano Zampini   }
6291674ae819SStefano Zampini   PetscFunctionReturn(0);
6292674ae819SStefano Zampini }
6293674ae819SStefano Zampini 
6294674ae819SStefano Zampini #undef __FUNCT__
6295674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
6296674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
6297674ae819SStefano Zampini {
629871582508SStefano Zampini   ISLocalToGlobalMapping map;
6299674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6300674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
630114f95afaSStefano Zampini   PetscInt               ierr,i,N;
6302674ae819SStefano Zampini 
6303674ae819SStefano Zampini   PetscFunctionBegin;
63048af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
6305b03ebc13SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
63068e61c736SStefano Zampini     /* Reset previously computed graph */
63078e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
6308674ae819SStefano Zampini     /* Init local Graph struct */
63097fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
631071582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
6311be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
6312674ae819SStefano Zampini 
6313575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
63149a962809SStefano 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);
63159577ea80SStefano Zampini 
6316674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
6317d4d8cf7bSStefano Zampini     if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
63184d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
63194d379d7bSStefano Zampini       PetscInt  nvtxs;
6320e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
6321674ae819SStefano Zampini 
63222fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
63232fffb893SStefano Zampini       if (flg_row) {
63244d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
6325b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
63262fffb893SStefano Zampini       }
63272fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
6328674ae819SStefano Zampini     }
63299b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
63309b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6331674ae819SStefano Zampini     }
6332674ae819SStefano Zampini 
6333674ae819SStefano Zampini     /* Setup of Graph */
63344b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
633514f95afaSStefano 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);
6336674ae819SStefano Zampini 
63374f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
63384f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
63394f1b2e48SStefano Zampini       PetscInt *local_subs;
63404f1b2e48SStefano Zampini 
63414f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
63424f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
63434f1b2e48SStefano Zampini         const PetscInt *idxs;
63444f1b2e48SStefano Zampini         PetscInt       nl,j;
63454f1b2e48SStefano Zampini 
63464f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
63474f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
634871582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
63494f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
63504f1b2e48SStefano Zampini       }
63514f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
63524f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
63534f1b2e48SStefano Zampini     }
63548af8fcf9SStefano Zampini   }
63554f1b2e48SStefano Zampini 
6356cac5312eSStefano Zampini   if (!pcbddc->graphanalyzed) {
6357674ae819SStefano Zampini     /* Graph's connected components analysis */
6358674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
635971582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
63608af8fcf9SStefano Zampini   }
6361674ae819SStefano Zampini   PetscFunctionReturn(0);
6362674ae819SStefano Zampini }
6363674ae819SStefano Zampini 
63649a7d3425SStefano Zampini #undef __FUNCT__
63659a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
63669a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
63679a7d3425SStefano Zampini {
63689a7d3425SStefano Zampini   PetscInt       i,j;
63699a7d3425SStefano Zampini   PetscScalar    *alphas;
63709a7d3425SStefano Zampini   PetscErrorCode ierr;
63719a7d3425SStefano Zampini 
63729a7d3425SStefano Zampini   PetscFunctionBegin;
6373785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
63749a7d3425SStefano Zampini   for (i=0;i<n;i++) {
63759a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
6376669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
6377669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
6378669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
63799a7d3425SStefano Zampini   }
63809a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
63819a7d3425SStefano Zampini   PetscFunctionReturn(0);
63829a7d3425SStefano Zampini }
63839a7d3425SStefano Zampini 
6384e7931f94SStefano Zampini #undef __FUNCT__
6385bb360cb4SStefano Zampini #define __FUNCT__ "PCBDDCMatISGetSubassemblingPattern"
6386bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
6387e7931f94SStefano Zampini {
638857de7509SStefano Zampini   Mat            A;
6389e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
6390e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
639152e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
639252e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
6393bb360cb4SStefano Zampini   PetscInt       im_active,active_procs,N,n,i,j,threshold = 2;
639457de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
639527b6a85dSStefano Zampini   PetscInt       xadj_count,*count;
639627b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
639727b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
639827b6a85dSStefano Zampini   MPI_Comm       subcomm;
639952e5ac9dSStefano Zampini   PetscErrorCode ierr;
6400a57a6d2fSStefano Zampini 
6401e7931f94SStefano Zampini   PetscFunctionBegin;
640257de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
640357de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
640457de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
640557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
640657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
640757de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
640857de7509SStefano Zampini 
640957de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
641057de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
641157de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
641257de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
641357de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
6414bb360cb4SStefano Zampini   im_active = !!n;
641557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
641657de7509SStefano Zampini   void_procs = size - active_procs;
641757de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
641857de7509SStefano Zampini   if (void_procs) {
641957de7509SStefano Zampini     PetscInt ncand;
642057de7509SStefano Zampini 
642157de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
642257de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
642357de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
642457de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
642557de7509SStefano Zampini       if (!procs_candidates[i]) {
642657de7509SStefano Zampini         procs_candidates[ncand++] = i;
642757de7509SStefano Zampini       }
642857de7509SStefano Zampini     }
642957de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
643057de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
643157de7509SStefano Zampini   }
643257de7509SStefano Zampini 
6433bb360cb4SStefano Zampini   /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix
643414f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
6435bb360cb4SStefano Zampini   ierr = MatGetSize(mat,&N,NULL);CHKERRQ(ierr);
6436bb360cb4SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) {
643714f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
643814f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
643914f0bfb9SStefano Zampini     else dest = rank;
644057de7509SStefano Zampini     if (im_active) {
644157de7509SStefano Zampini       issize = 1;
644257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
644314f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
644457de7509SStefano Zampini       } else {
644514f0bfb9SStefano Zampini         isidx = dest;
644657de7509SStefano Zampini       }
644757de7509SStefano Zampini     } else {
644857de7509SStefano Zampini       issize = 0;
644957de7509SStefano Zampini       isidx = -1;
645057de7509SStefano Zampini     }
6451bb360cb4SStefano Zampini     if (*n_subdomains != 1) *n_subdomains = active_procs;
645257de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6453daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
645457de7509SStefano Zampini     PetscFunctionReturn(0);
645557de7509SStefano Zampini   }
6456c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6457c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
645827b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6459e7931f94SStefano Zampini 
6460e7931f94SStefano Zampini   /* Get info on mapping */
64613bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6462e7931f94SStefano Zampini 
6463e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6464785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6465e7931f94SStefano Zampini   xadj[0] = 0;
6466e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6467785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6468785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
6469bb360cb4SStefano Zampini   ierr = PetscCalloc1(n,&count);CHKERRQ(ierr);
647027b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
647127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
647227b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6473e7931f94SStefano Zampini 
647427b6a85dSStefano Zampini   xadj_count = 0;
64752b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
647627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
647727b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6478d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6479d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6480d023bfaeSStefano Zampini         xadj_count++;
648127b6a85dSStefano Zampini         break;
648227b6a85dSStefano Zampini       }
6483e7931f94SStefano Zampini     }
6484e7931f94SStefano Zampini   }
6485d023bfaeSStefano Zampini   xadj[1] = xadj_count;
648627b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
64873bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6488e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6489e7931f94SStefano Zampini 
64903837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6491e7931f94SStefano Zampini 
649227b6a85dSStefano Zampini   /* Restrict work on active processes only */
649327b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
649427b6a85dSStefano Zampini   if (void_procs) {
649527b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
649627b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
649727b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
649827b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
649927b6a85dSStefano Zampini   } else {
650027b6a85dSStefano Zampini     psubcomm = NULL;
650127b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
650227b6a85dSStefano Zampini   }
650327b6a85dSStefano Zampini 
650427b6a85dSStefano Zampini   v_wgt = NULL;
650527b6a85dSStefano Zampini   if (!color) {
6506e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6507e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6508e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6509c8587f34SStefano Zampini   } else {
651052e5ac9dSStefano Zampini     Mat             subdomain_adj;
651152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
651252e5ac9dSStefano Zampini     MatPartitioning partitioner;
651327b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
651452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
651557de7509SStefano Zampini     PetscMPIInt     size;
6516b0c7d250SStefano Zampini     PetscBool       aggregate;
6517b0c7d250SStefano Zampini 
651827b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
651927b6a85dSStefano Zampini     if (void_procs) {
652027b6a85dSStefano Zampini       PetscInt prank = rank;
6521785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
652227b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6523e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6524e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6525c8587f34SStefano Zampini       }
6526e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
652727b6a85dSStefano Zampini     } else {
652827b6a85dSStefano Zampini       oldranks = NULL;
652927b6a85dSStefano Zampini     }
6530b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
653127b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6532b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6533b0c7d250SStefano Zampini       PetscMPIInt nrank;
6534b0c7d250SStefano Zampini       PetscScalar *vals;
6535b0c7d250SStefano Zampini 
653627b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6537b0c7d250SStefano Zampini       lrows = 0;
6538b0c7d250SStefano Zampini       if (nrank<redprocs) {
6539b0c7d250SStefano Zampini         lrows = size/redprocs;
6540b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6541b0c7d250SStefano Zampini       }
654227b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6543b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6544b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6545b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6546b0c7d250SStefano Zampini       row = nrank;
6547b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6548b0c7d250SStefano Zampini       cols = adjncy;
6549b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6550b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6551b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6552b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6553b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
655452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
655552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
655652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6557b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
655827b6a85dSStefano Zampini       if (use_vwgt) {
655927b6a85dSStefano Zampini         Vec               v;
656027b6a85dSStefano Zampini         const PetscScalar *array;
656127b6a85dSStefano Zampini         PetscInt          nl;
656227b6a85dSStefano Zampini 
656327b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
6564bb360cb4SStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES);CHKERRQ(ierr);
656527b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
656627b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
656727b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
656827b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
656927b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
657022db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
657127b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
657227b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
657327b6a85dSStefano Zampini       }
6574b0c7d250SStefano Zampini     } else {
657527b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
657627b6a85dSStefano Zampini       if (use_vwgt) {
657727b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
6578bb360cb4SStefano Zampini         v_wgt[0] = n;
657927b6a85dSStefano Zampini       }
6580b0c7d250SStefano Zampini     }
658122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6582e7931f94SStefano Zampini 
6583e7931f94SStefano Zampini     /* Partition */
658427b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6585e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
658627b6a85dSStefano Zampini     if (v_wgt) {
6587e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6588c8587f34SStefano Zampini     }
658957de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
659057de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6591e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6592e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
659322b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6594e7931f94SStefano Zampini 
659552e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
65966583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
659752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
659852e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
659957de7509SStefano Zampini     if (!aggregate) {
660057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
660127b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
660227b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
660327b6a85dSStefano Zampini #endif
660457de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
660527b6a85dSStefano Zampini       } else if (oldranks) {
6606b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
660727b6a85dSStefano Zampini       } else {
660827b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
660957de7509SStefano Zampini       }
661028143c3dSStefano Zampini     } else {
6611b0c7d250SStefano Zampini       PetscInt    idxs[1];
6612b0c7d250SStefano Zampini       PetscMPIInt tag;
6613b0c7d250SStefano Zampini       MPI_Request *reqs;
6614b0c7d250SStefano Zampini 
6615b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6616b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6617b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
661827b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
661928143c3dSStefano Zampini       }
662027b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6621b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6622b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
662357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
662427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
662527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
662627b6a85dSStefano Zampini #endif
662757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
662827b6a85dSStefano Zampini       } else if (oldranks) {
6629b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
663027b6a85dSStefano Zampini       } else {
663127b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6632e7931f94SStefano Zampini       }
663357de7509SStefano Zampini     }
663452e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6635e7931f94SStefano Zampini     /* clean up */
6636e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
663752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6638e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6639e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6640e7931f94SStefano Zampini   }
664127b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
664257de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6643e7931f94SStefano Zampini 
6644e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6645e7931f94SStefano Zampini   i = 1;
664627b6a85dSStefano Zampini   if (!color) i=0;
664757de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6648e7931f94SStefano Zampini   PetscFunctionReturn(0);
6649e7931f94SStefano Zampini }
6650e7931f94SStefano Zampini 
6651e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6652e7931f94SStefano Zampini 
6653e7931f94SStefano Zampini #undef __FUNCT__
66541e0482f5SStefano Zampini #define __FUNCT__ "PCBDDCMatISSubassemble"
66551e0482f5SStefano 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[])
6656e7931f94SStefano Zampini {
665770cf5478SStefano Zampini   Mat                    local_mat;
6658e7931f94SStefano Zampini   IS                     is_sends_internal;
66599d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
66601ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
66619d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6662e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6663e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6664e7931f94SStefano Zampini   const PetscInt*        is_indices;
6665e7931f94SStefano Zampini   MatType                new_local_type;
6666e7931f94SStefano Zampini   /* buffers */
6667e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
666828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
66699d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6670e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
66711ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6672e7931f94SStefano Zampini   /* MPI */
667328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
667428143c3dSStefano Zampini   PetscSubcomm           subcomm;
6675e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
667628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
667728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
66781ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
66791ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
66801ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6681e7931f94SStefano Zampini   PetscErrorCode         ierr;
6682e7931f94SStefano Zampini 
6683e7931f94SStefano Zampini   PetscFunctionBegin;
668457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6685e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
668628143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
668757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
668857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
668957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
669057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
669157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
66921ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
66931ae86dd6SStefano Zampini   if (nvecs) {
66941ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
66951ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
66961ae86dd6SStefano Zampini   }
669757de7509SStefano Zampini   /* further checks */
6698e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6699e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6700e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6701e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6702e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
670357de7509SStefano Zampini   if (reuse && *mat_n) {
670470cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
670557de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
670670cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
670728143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
670870cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
670970cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
671070cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
671170cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
671270cf5478SStefano Zampini   }
6713e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6714e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
671557de7509SStefano Zampini 
6716e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6717e7931f94SStefano Zampini   if (!is_sends) {
671828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
6719bb360cb4SStefano Zampini     ierr = PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6720c8587f34SStefano Zampini   } else {
6721e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6722e7931f94SStefano Zampini     is_sends_internal = is_sends;
6723c8587f34SStefano Zampini   }
6724e7931f94SStefano Zampini 
6725e7931f94SStefano Zampini   /* get comm */
6726a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6727e7931f94SStefano Zampini 
6728e7931f94SStefano Zampini   /* compute number of sends */
6729e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6730e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6731e7931f94SStefano Zampini 
6732e7931f94SStefano Zampini   /* compute number of receives */
6733e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6734785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6735e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6736e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6737e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6738e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6739e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6740e7931f94SStefano Zampini 
674128143c3dSStefano Zampini   /* restrict comm if requested */
674228143c3dSStefano Zampini   subcomm = 0;
674328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
674428143c3dSStefano Zampini   if (restrict_comm) {
6745779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6746779c1cceSStefano Zampini 
674728143c3dSStefano Zampini     color = 0;
674853a05cb3SStefano Zampini     if (restrict_full) {
674953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
675053a05cb3SStefano Zampini     } else {
675153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
675253a05cb3SStefano Zampini     }
6753b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
675428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
675528143c3dSStefano Zampini     /* check if reuse has been requested */
675657de7509SStefano Zampini     if (reuse) {
675728143c3dSStefano Zampini       if (*mat_n) {
675828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
675928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
676028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
676128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
676228143c3dSStefano Zampini       } else {
676328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
676428143c3dSStefano Zampini       }
676528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6766779c1cceSStefano Zampini       PetscMPIInt rank;
6767779c1cceSStefano Zampini 
6768779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
676928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
677028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
677128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6772306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
677328143c3dSStefano Zampini     }
677428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
677528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
677628143c3dSStefano Zampini   } else {
677728143c3dSStefano Zampini     comm_n = comm;
677828143c3dSStefano Zampini   }
677928143c3dSStefano Zampini 
6780e7931f94SStefano Zampini   /* prepare send/receive buffers */
6781785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6782e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6783785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6784e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
678528143c3dSStefano Zampini   if (nis) {
6786854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
678728143c3dSStefano Zampini   }
6788e7931f94SStefano Zampini 
678928143c3dSStefano Zampini   /* Get data from local matrices */
67906c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6791e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6792e7931f94SStefano Zampini     /*
6793e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6794e7931f94SStefano Zampini        send_buffer_idxs should contain:
6795e7931f94SStefano Zampini        - MatType_PRIVATE type
6796e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6797e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6798e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6799e7931f94SStefano Zampini     */
68006c4ed002SBarry Smith   else {
6801e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
68023bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6803854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6804e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6805e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
68063bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6807e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
68083bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6809e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6810e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6811e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6812e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6813c8587f34SStefano Zampini     }
6814c8587f34SStefano Zampini   }
6815e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
681628143c3dSStefano Zampini   /* additional is (if any) */
681728143c3dSStefano Zampini   if (nis) {
681828143c3dSStefano Zampini     PetscMPIInt psum;
681928143c3dSStefano Zampini     PetscInt j;
682028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
682128143c3dSStefano Zampini       PetscInt plen;
682228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
682328143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
682428143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
682528143c3dSStefano Zampini     }
6826854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
682728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
682828143c3dSStefano Zampini       PetscInt plen;
682928143c3dSStefano Zampini       const PetscInt *is_array_idxs;
683028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
683128143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
683228143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
683328143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
683428143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
683528143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
683628143c3dSStefano Zampini     }
683728143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
683828143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
683928143c3dSStefano Zampini     }
684028143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
684128143c3dSStefano Zampini   }
684228143c3dSStefano Zampini 
6843e7931f94SStefano Zampini   buf_size_idxs = 0;
6844e7931f94SStefano Zampini   buf_size_vals = 0;
684528143c3dSStefano Zampini   buf_size_idxs_is = 0;
68461ae86dd6SStefano Zampini   buf_size_vecs = 0;
6847e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6848e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6849e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
685028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
68511ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6852e7931f94SStefano Zampini   }
6853785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6854785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
685595ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
68561ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6857e7931f94SStefano Zampini 
6858e7931f94SStefano Zampini   /* get new tags for clean communications */
6859e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6860e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
686128143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
68621ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6863e7931f94SStefano Zampini 
6864e7931f94SStefano Zampini   /* allocate for requests */
6865785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6866785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
686795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
68681ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6869785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6870785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
687195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
68721ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6873e7931f94SStefano Zampini 
6874e7931f94SStefano Zampini   /* communications */
6875e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6876e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
687728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
68781ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6879e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6880e7931f94SStefano Zampini     source_dest = onodes[i];
6881e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6882e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6883e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6884e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
688528143c3dSStefano Zampini     if (nis) {
688657de7509SStefano Zampini       source_dest = onodes_is[i];
688728143c3dSStefano 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);
688828143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
688928143c3dSStefano Zampini     }
68901ae86dd6SStefano Zampini     if (nvecs) {
68911ae86dd6SStefano Zampini       source_dest = onodes[i];
68921ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
68931ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
68941ae86dd6SStefano Zampini     }
6895e7931f94SStefano Zampini   }
6896e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6897e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6898e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6899e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
690028143c3dSStefano Zampini     if (nis) {
690128143c3dSStefano 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);
690228143c3dSStefano Zampini     }
69031ae86dd6SStefano Zampini     if (nvecs) {
69041ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
69051ae86dd6SStefano 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);
69061ae86dd6SStefano Zampini     }
6907e7931f94SStefano Zampini   }
6908e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6909e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6910e7931f94SStefano Zampini 
6911e7931f94SStefano Zampini   /* assemble new l2g map */
6912e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6913e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
69149d30be91SStefano Zampini   new_local_rows = 0;
6915e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
69169d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6917e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6918e7931f94SStefano Zampini   }
69199d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6920e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
69219d30be91SStefano Zampini   new_local_rows = 0;
6922e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
69239d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
69249d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6925e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6926e7931f94SStefano Zampini   }
69279d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
69289d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6929e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6930e7931f94SStefano Zampini 
6931e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6932e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6933e7931f94SStefano 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) */
6934e7931f94SStefano Zampini   if (n_recvs) {
693528143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6936e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6937e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6938e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6939e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6940e7931f94SStefano Zampini         break;
6941e7931f94SStefano Zampini       }
6942e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6943e7931f94SStefano Zampini     }
6944e7931f94SStefano Zampini     switch (new_local_type_private) {
694528143c3dSStefano Zampini       case MATDENSE_PRIVATE:
694628143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6947e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6948e7931f94SStefano Zampini           bs = 1;
694928143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
695028143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
695128143c3dSStefano Zampini           bs = 1;
695228143c3dSStefano Zampini         }
6953e7931f94SStefano Zampini         break;
6954e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6955e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6956e7931f94SStefano Zampini         bs = 1;
6957e7931f94SStefano Zampini         break;
6958e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6959e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6960e7931f94SStefano Zampini         break;
6961e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6962e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6963e7931f94SStefano Zampini         break;
6964e7931f94SStefano Zampini       default:
69659d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6966e7931f94SStefano Zampini         break;
6967e7931f94SStefano Zampini     }
696828143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
696928143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
697028143c3dSStefano Zampini     bs = 1;
6971e7931f94SStefano Zampini   }
6972e7931f94SStefano Zampini 
697370cf5478SStefano Zampini   /* create MATIS object if needed */
697457de7509SStefano Zampini   if (!reuse) {
6975e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6976e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
697770cf5478SStefano Zampini   } else {
697870cf5478SStefano Zampini     /* it also destroys the local matrices */
697957de7509SStefano Zampini     if (*mat_n) {
698070cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
698157de7509SStefano Zampini     } else { /* this is a fake object */
698257de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
698357de7509SStefano Zampini     }
698470cf5478SStefano Zampini   }
698570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6986e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
69879d30be91SStefano Zampini 
69889d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
69899d30be91SStefano Zampini 
69909d30be91SStefano Zampini   /* Global to local map of received indices */
69919d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
69929d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
69939d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
69949d30be91SStefano Zampini 
69959d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
69969d30be91SStefano Zampini   buf_size_idxs = 0;
69979d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
69989d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
69999d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
70009d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
70019d30be91SStefano Zampini   }
70029d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
70039d30be91SStefano Zampini 
70049d30be91SStefano Zampini   /* set preallocation */
70059d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
70069d30be91SStefano Zampini   if (!newisdense) {
70079d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
70089d30be91SStefano Zampini 
70099d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
70109d30be91SStefano Zampini     if (n_recvs) {
70119d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
70129d30be91SStefano Zampini     }
70139d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
70149d30be91SStefano Zampini       PetscInt j;
70159d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
70169d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
70179d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
70189d30be91SStefano Zampini         }
70199d30be91SStefano Zampini       } else {
70209d30be91SStefano Zampini         /* TODO */
70219d30be91SStefano Zampini       }
70229d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
70239d30be91SStefano Zampini     }
70249d30be91SStefano Zampini     if (new_local_nnz) {
70259d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
70269d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
70279d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
70289d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
70299d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
70309d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
70319d30be91SStefano Zampini     } else {
70329d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
70339d30be91SStefano Zampini     }
70349d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
70359d30be91SStefano Zampini   } else {
70369d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
70379d30be91SStefano Zampini   }
7038e7931f94SStefano Zampini 
7039e7931f94SStefano Zampini   /* set values */
7040e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
70419d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
7042e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
7043e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
7044e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
70459d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
7046e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7047e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
7048e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
704928143c3dSStefano Zampini     } else {
705028143c3dSStefano Zampini       /* TODO */
7051e7931f94SStefano Zampini     }
7052e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
7053e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
7054e7931f94SStefano Zampini   }
7055e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7056e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
705770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
705870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70599d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
7060e7931f94SStefano Zampini 
7061dfd14d43SStefano Zampini #if 0
706228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
7063e7931f94SStefano Zampini     Vec       lvec,rvec;
7064e7931f94SStefano Zampini     PetscReal infty_error;
7065e7931f94SStefano Zampini 
70662a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
7067e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
7068e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
7069e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
707070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
7071e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
7072e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
7073e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
7074e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
7075e7931f94SStefano Zampini   }
707628143c3dSStefano Zampini #endif
7077e7931f94SStefano Zampini 
707828143c3dSStefano Zampini   /* assemble new additional is (if any) */
707928143c3dSStefano Zampini   if (nis) {
708028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
708128143c3dSStefano Zampini 
708228143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7083854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
708428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
708528143c3dSStefano Zampini     psum = 0;
708628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
708728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
708828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
708928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
709028143c3dSStefano Zampini         psum += plen;
709128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
709228143c3dSStefano Zampini       }
709328143c3dSStefano Zampini     }
7094854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
7095854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
709628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
709728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
709828143c3dSStefano Zampini     }
709928143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
710028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
710128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
710228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
710328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
710428143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
710528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
710628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
710728143c3dSStefano Zampini       }
710828143c3dSStefano Zampini     }
710928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
711028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
711128143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
711228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
711328143c3dSStefano Zampini     }
711428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
711528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
711628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
711728143c3dSStefano Zampini   }
7118e7931f94SStefano Zampini   /* free workspace */
711928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
7120e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7121e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
7122e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
7123e7931f94SStefano Zampini   if (isdense) {
7124e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
7125e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
7126e7931f94SStefano Zampini   } else {
7127e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
7128e7931f94SStefano Zampini   }
712928143c3dSStefano Zampini   if (nis) {
713028143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
713128143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
713228143c3dSStefano Zampini   }
71331ae86dd6SStefano Zampini 
71341ae86dd6SStefano Zampini   if (nvecs) {
71351ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
71361ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
71371ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
71381ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
71391ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
71401ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
71411ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
71421ae86dd6SStefano Zampini     /* set values */
71431ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
71441ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
71451ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
71461ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
71471ae86dd6SStefano Zampini       PetscInt j;
71481ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
71491ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
71501ae86dd6SStefano Zampini       }
71511ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
71521ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
71531ae86dd6SStefano Zampini     }
71541ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
71551ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
71561ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
71571ae86dd6SStefano Zampini   }
71581ae86dd6SStefano Zampini 
71591ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
71601ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
7161e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
7162e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
71631ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
716428143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
7165e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
7166e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
71671ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
716828143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
7169e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
7170e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
7171e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
7172e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
7173e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
717428143c3dSStefano Zampini   if (nis) {
717528143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
717628143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
717728143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
717828143c3dSStefano Zampini   }
717928143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
718028143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
718128143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
718228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
718328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
718428143c3dSStefano Zampini     }
71851ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
71861ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
71871ae86dd6SStefano Zampini     }
718853a05cb3SStefano Zampini     *mat_n = NULL;
718928143c3dSStefano Zampini   }
7190e7931f94SStefano Zampini   PetscFunctionReturn(0);
7191e7931f94SStefano Zampini }
7192a57a6d2fSStefano Zampini 
719312edc857SStefano Zampini /* temporary hack into ksp private data structure */
7194af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
719512edc857SStefano Zampini 
7196c8587f34SStefano Zampini #undef __FUNCT__
7197c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
7198c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
7199c8587f34SStefano Zampini {
7200c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
7201c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
720220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
72031ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
72041e0482f5SStefano Zampini   Mat                    coarseG,t_coarse_mat_is;
72059881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
720620a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
72076e683305SStefano Zampini   IS                     coarse_is,*isarray;
72086e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
720930368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
7210f9eb5b7dSStefano Zampini   PC                     pc_temp;
7211c8587f34SStefano Zampini   PCType                 coarse_pc_type;
7212c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
7213f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
72144f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
72151e0482f5SStefano Zampini   PetscInt               ncoarse,nedcfield;
721668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
721722bc73bbSStefano Zampini   PetscScalar            *array;
721857de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
721957de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
72209881197aSStefano Zampini   PetscErrorCode         ierr;
7221fdc09c96SStefano Zampini 
7222c8587f34SStefano Zampini   PetscFunctionBegin;
7223c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
722468457ee5SStefano 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 */
7225fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
72265a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
7227fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
7228f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
7229f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
7230f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
7231fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
723251bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
723351bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
7234dc4bcba2SStefano Zampini         PC        pc;
7235dc4bcba2SStefano Zampini         PetscBool isbddc;
7236dc4bcba2SStefano Zampini 
7237dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
7238dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
7239dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
7240dc4bcba2SStefano Zampini         if (isbddc) {
724163c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
724263c961adSStefano Zampini         } else {
7243727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
724463c961adSStefano Zampini         }
7245fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
7246fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
7247fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
7248f4ddd8eeSStefano Zampini       }
7249fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
7250fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
7251f4ddd8eeSStefano Zampini     }
725270cf5478SStefano Zampini     /* reset any subassembling information */
725357de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
725470cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
725557de7509SStefano Zampini     }
72566e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
7257fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
7258f4ddd8eeSStefano Zampini   }
725957de7509SStefano Zampini   /* assemble coarse matrix */
726057de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
726157de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
726257de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
726357de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
726418a45a71SStefano Zampini   } else {
726557de7509SStefano Zampini     coarse_mat = NULL;
726657de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
72676e683305SStefano Zampini   }
7268e7931f94SStefano Zampini 
7269abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
7270abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
7271abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
7272abbbba34SStefano Zampini 
7273abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
727422bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
727522bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
727622bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
727722bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
7278e176bc59SStefano 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);
72796e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
72806e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
72816e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7282abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
7283abbbba34SStefano Zampini 
728457de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
728557de7509SStefano Zampini   im_active = !!(pcis->n);
728657de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
728757de7509SStefano Zampini 
728814f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
728957de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
729057de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
729157de7509SStefano Zampini   coarse_mat_is = NULL;
729257de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
729357de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
72941ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
729557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
729657de7509SStefano Zampini   if (multilevel_requested) {
729757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
729857de7509SStefano Zampini     restr = PETSC_FALSE;
729957de7509SStefano Zampini     full_restr = PETSC_FALSE;
730057de7509SStefano Zampini   } else {
730157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
730257de7509SStefano Zampini     restr = PETSC_TRUE;
730357de7509SStefano Zampini     full_restr = PETSC_TRUE;
730457de7509SStefano Zampini   }
73054b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
730657de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
730757de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
7308a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
7309bb360cb4SStefano Zampini       if (multilevel_requested) {
7310bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7311bb360cb4SStefano Zampini       } else {
7312bb360cb4SStefano Zampini         ierr = PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
7313bb360cb4SStefano Zampini       }
7314a198735bSStefano Zampini     } else {
7315a198735bSStefano Zampini       PetscMPIInt size,rank;
7316a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
7317a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
7318a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
7319a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
7320a198735bSStefano Zampini     }
732157de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
732257de7509SStefano Zampini     PetscInt    psum;
732357de7509SStefano Zampini     PetscMPIInt size;
732457de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
732557de7509SStefano Zampini     else psum = 0;
732657de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
732757de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
732857de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
732957de7509SStefano Zampini   }
733057de7509SStefano Zampini   /* determine if we can go multilevel */
733157de7509SStefano Zampini   if (multilevel_requested) {
733257de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
733357de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
733457de7509SStefano Zampini   }
733557de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
733657de7509SStefano Zampini 
7337e4d548c7SStefano Zampini   /* dump subassembling pattern */
7338e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
7339e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
7340e4d548c7SStefano Zampini   }
7341e4d548c7SStefano Zampini 
73426e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
73431e0482f5SStefano Zampini   nedcfield = -1;
73441e0482f5SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal)) { /* protects from unneded computations */
73456e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
73466e683305SStefano Zampini     const PetscInt         *idxs;
73476e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
73486e683305SStefano Zampini 
73496e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
73500be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
73516e683305SStefano Zampini     /* allocate space for temporary storage */
7352854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
7353854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
73546e683305SStefano Zampini     /* allocate for IS array */
73556e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
73561e0482f5SStefano Zampini     if (pcbddc->nedclocal) {
73571e0482f5SStefano Zampini       if (pcbddc->nedfield > -1) {
73581e0482f5SStefano Zampini         nedcfield = pcbddc->nedfield;
73591e0482f5SStefano Zampini       } else {
73601e0482f5SStefano Zampini         nedcfield = 0;
73611e0482f5SStefano Zampini         if (nisdofs) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%d)",nisdofs);
73621e0482f5SStefano Zampini         nisdofs = 1;
73631e0482f5SStefano Zampini       }
73641e0482f5SStefano Zampini     }
73656e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
736627b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
736730368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
7368854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
73696e683305SStefano Zampini     /* dofs splitting */
73706e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
73716e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
73721e0482f5SStefano Zampini       if (nedcfield != i) {
73736e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
73746e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
73756e683305SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
73766e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
73771e0482f5SStefano Zampini       } else {
73781e0482f5SStefano Zampini         ierr = ISGetLocalSize(pcbddc->nedclocal,&tsize);CHKERRQ(ierr);
73791e0482f5SStefano Zampini         ierr = ISGetIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
73801e0482f5SStefano Zampini         ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
7381eee23b56SStefano Zampini         if (tsize != nout) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %d != %d\n",tsize,nout);
73821e0482f5SStefano Zampini         ierr = ISRestoreIndices(pcbddc->nedclocal,&idxs);CHKERRQ(ierr);
73831e0482f5SStefano Zampini       }
73846e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
738530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
73866e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
73876e683305SStefano Zampini     }
73886e683305SStefano Zampini     /* neumann boundaries */
73896e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
73906e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
73916e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
73926e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
73936e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
73946e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
73956e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
739630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
73976e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
73986e683305SStefano Zampini     }
73996e683305SStefano Zampini     /* free memory */
74006e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
74016e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
74026e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
74036e683305SStefano Zampini   } else {
74046e683305SStefano Zampini     nis = 0;
74056e683305SStefano Zampini     nisdofs = 0;
74066e683305SStefano Zampini     nisneu = 0;
740730368db7SStefano Zampini     nisvert = 0;
74086e683305SStefano Zampini     isarray = NULL;
74096e683305SStefano Zampini   }
74106e683305SStefano Zampini   /* destroy no longer needed map */
74116e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
74126e683305SStefano Zampini 
741357de7509SStefano Zampini   /* subassemble */
741457de7509SStefano Zampini   if (multilevel_allowed) {
74151ae86dd6SStefano Zampini     Vec       vp[1];
74161ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
741757de7509SStefano Zampini     PetscBool reuse,reuser;
74181ae86dd6SStefano Zampini 
741957de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
742057de7509SStefano Zampini     else reuse = PETSC_FALSE;
742157de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
74221ae86dd6SStefano Zampini     vp[0] = NULL;
74231ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
74241ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
74251ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
74261ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
74271ae86dd6SStefano Zampini       nvecs = 1;
74281ae86dd6SStefano Zampini 
74291ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
7430a198735bSStefano Zampini         Mat      B,loc_divudotp;
74311ae86dd6SStefano Zampini         Vec      v,p;
74321ae86dd6SStefano Zampini         IS       dummy;
74331ae86dd6SStefano Zampini         PetscInt np;
74341ae86dd6SStefano Zampini 
7435a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
7436a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
74371ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
7438a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
74391ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
74401ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
74411ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
74421ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
74431ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
74441ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
74451ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
74461ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
74471ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
74481ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
74491ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
74501ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
745174e2c79eSStefano Zampini       }
74521ae86dd6SStefano Zampini     }
74531ae86dd6SStefano Zampini     if (reuser) {
74541e0482f5SStefano Zampini       ierr = PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
745574e2c79eSStefano Zampini     } else {
74561e0482f5SStefano 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);
74571ae86dd6SStefano Zampini     }
74581ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
74591ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
74601ae86dd6SStefano Zampini       PetscInt    nl;
74611ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
74621ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
74631ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
74641ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
74651ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
74661ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
74671ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
74681ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7469a198735bSStefano Zampini     } else {
7470a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
74711ae86dd6SStefano Zampini     }
74721ae86dd6SStefano Zampini   } else {
74731e0482f5SStefano 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);
74746e683305SStefano Zampini   }
747557de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
747657de7509SStefano Zampini     PetscMPIInt size;
7477f913dca9SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);CHKERRQ(ierr);
747857de7509SStefano Zampini     if (!multilevel_allowed) {
747957de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
74806e683305SStefano Zampini     } else {
748157de7509SStefano Zampini       Mat A;
7482779c1cceSStefano Zampini 
748357de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
748457de7509SStefano Zampini       if (coarse_mat_is) {
748557de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
748657de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
748757de7509SStefano Zampini         coarse_mat = coarse_mat_is;
748857de7509SStefano Zampini       }
748957de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
749057de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
749157de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7492779c1cceSStefano Zampini     }
7493779c1cceSStefano Zampini   }
749457de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
749557de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
74966e683305SStefano Zampini 
74976e683305SStefano Zampini   /* create local to global scatters for coarse problem */
749868457ee5SStefano Zampini   if (compute_vecs) {
74996e683305SStefano Zampini     PetscInt lrows;
75006e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
750157de7509SStefano Zampini     if (coarse_mat) {
750257de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
75036e683305SStefano Zampini     } else {
75046e683305SStefano Zampini       lrows = 0;
75056e683305SStefano Zampini     }
75066e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
75076e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
75086e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
75096e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
75106e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
75116e683305SStefano Zampini   }
75126e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7513c8587f34SStefano Zampini 
7514f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7515f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7516f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7517f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7518f9eb5b7dSStefano Zampini   } else {
7519f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7520f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7521c8587f34SStefano Zampini   }
7522c8587f34SStefano Zampini 
75236e683305SStefano Zampini   /* print some info if requested */
75246e683305SStefano Zampini   if (pcbddc->dbg_flag) {
75256e683305SStefano Zampini     if (!multilevel_allowed) {
75266e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
75276e683305SStefano Zampini       if (multilevel_requested) {
75286e683305SStefano 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);
75296e683305SStefano Zampini       } else if (pcbddc->max_levels) {
75306e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
75316e683305SStefano Zampini       }
75326e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
75336e683305SStefano Zampini     }
75346e683305SStefano Zampini   }
75356e683305SStefano Zampini 
75361e0482f5SStefano Zampini   /* communicate coarse discrete gradient */
75371e0482f5SStefano Zampini   coarseG = NULL;
75381e0482f5SStefano Zampini   if (pcbddc->nedcG && multilevel_allowed) {
75391e0482f5SStefano Zampini     MPI_Comm ccomm;
75401e0482f5SStefano Zampini     if (coarse_mat) {
75411e0482f5SStefano Zampini       ccomm = PetscObjectComm((PetscObject)coarse_mat);
75421e0482f5SStefano Zampini     } else {
75431e0482f5SStefano Zampini       ccomm = MPI_COMM_NULL;
75441e0482f5SStefano Zampini     }
75451e0482f5SStefano Zampini     ierr = MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG);CHKERRQ(ierr);
75461e0482f5SStefano Zampini   }
75471e0482f5SStefano Zampini 
7548f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
754957de7509SStefano Zampini   if (coarse_mat) {
75506a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
75516e683305SStefano Zampini     if (pcbddc->dbg_flag) {
755257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
75536e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
75546e683305SStefano Zampini     }
7555f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7556312be037SStefano Zampini       char prefix[256],str_level[16];
7557e604994aSStefano Zampini       size_t len;
75581e0482f5SStefano Zampini 
755957de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7560422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7561c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7562f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
756357de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7564c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
75656e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7566c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
75671e0482f5SStefano Zampini       /* TODO is this logic correct? should check for coarse_mat type */
7568c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7569e604994aSStefano Zampini       /* prefix */
7570e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7571e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7572e604994aSStefano Zampini       if (!pcbddc->current_level) {
7573e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7574e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7575c8587f34SStefano Zampini       } else {
7576e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7577312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7578312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
757934d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7580312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7581e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7582e604994aSStefano Zampini       }
7583e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
75843e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
75853e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
75863e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
75873e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7588f9eb5b7dSStefano Zampini       /* allow user customization */
7589f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
75903e3c6dadSStefano Zampini     }
75913e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
759251bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
75933e3c6dadSStefano Zampini     if (nisdofs) {
75943e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
75953e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
75963e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
75973e3c6dadSStefano Zampini       }
75983e3c6dadSStefano Zampini     }
75993e3c6dadSStefano Zampini     if (nisneu) {
76003e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
76013e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7602312be037SStefano Zampini     }
760330368db7SStefano Zampini     if (nisvert) {
760430368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
760530368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
760630368db7SStefano Zampini     }
76071e0482f5SStefano Zampini     if (coarseG) {
76081e0482f5SStefano Zampini       ierr = PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
76091e0482f5SStefano Zampini     }
7610f9eb5b7dSStefano Zampini 
7611f9eb5b7dSStefano Zampini     /* get some info after set from options */
7612f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7613f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
76144f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
76156e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7616f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7617f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7618f9eb5b7dSStefano Zampini     }
761939f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
76204f3a063dSStefano Zampini     if (isredundant) {
76214f3a063dSStefano Zampini       KSP inner_ksp;
76224f3a063dSStefano Zampini       PC  inner_pc;
76234f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
76244f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
76254f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
76264f3a063dSStefano Zampini     }
7627f9eb5b7dSStefano Zampini 
762857de7509SStefano Zampini     /* parameters which miss an API */
762957de7509SStefano Zampini     if (isbddc) {
7630720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7631720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
763257de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
763327b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
763427b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7635a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7636a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7637a198735bSStefano Zampini         IS                     row,col;
7638a198735bSStefano Zampini         const PetscInt         *gidxs;
7639a198735bSStefano Zampini         PetscInt               n,st,M,N;
7640a198735bSStefano Zampini 
7641a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7642a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7643a198735bSStefano Zampini         st = st-n;
7644a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7645a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7646a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7647a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7648a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7649a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7650a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7651a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7652a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7653a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7654a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7655a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7656a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7657a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7658a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7659a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7660a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7661a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7662a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7663a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
76648ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7665a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7666720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
766759e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7668720d30f9SStefano Zampini       }
7669d4d8cf7bSStefano Zampini     }
76709881197aSStefano Zampini 
76713301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
76725a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
76733301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
76743301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
76753301b35fSStefano Zampini     }
76763301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
76773301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
76783301b35fSStefano Zampini     }
76793301b35fSStefano Zampini     if (pc->pmat->spd_set) {
76803301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
76813301b35fSStefano Zampini     }
768227b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
768327b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
768427b6a85dSStefano Zampini     }
76856e683305SStefano Zampini     /* set operators */
76865f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
76876e683305SStefano Zampini     if (pcbddc->dbg_flag) {
76886e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
76896e683305SStefano Zampini     }
76906e683305SStefano Zampini   }
76911e0482f5SStefano Zampini   ierr = MatDestroy(&coarseG);CHKERRQ(ierr);
76926e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7693b1ecc7b1SStefano Zampini #if 0
7694b9b85e73SStefano Zampini   {
7695b9b85e73SStefano Zampini     PetscViewer viewer;
7696b9b85e73SStefano Zampini     char filename[256];
7697b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7698b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
76996a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7700b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7701f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7702b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7703b9b85e73SStefano Zampini   }
7704b9b85e73SStefano Zampini #endif
7705f9eb5b7dSStefano Zampini 
770698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
770798a51de6SStefano Zampini     Vec crhs,csol;
770804708bb6SStefano Zampini 
7709f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7710f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7711f347579bSStefano Zampini     if (!csol) {
77122a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7713f9eb5b7dSStefano Zampini     }
7714f347579bSStefano Zampini     if (!crhs) {
77152a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7716f347579bSStefano Zampini     }
7717b0f5fe93SStefano Zampini   }
77181ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7719b0f5fe93SStefano Zampini 
7720b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7721b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7722b0f5fe93SStefano Zampini 
7723b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
77244f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
77254f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
77264f1b2e48SStefano Zampini     }
7727b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7728b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7729b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7730b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7731b0f5fe93SStefano Zampini     if (coarse_mat) {
7732b0f5fe93SStefano Zampini       Vec         nullv;
7733b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7734b0f5fe93SStefano Zampini       PetscInt    nl;
7735b0f5fe93SStefano Zampini 
7736b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7737b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7738b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7739b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7740b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7741b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7742b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7743b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7744b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7745b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7746b0f5fe93SStefano Zampini     }
7747b0f5fe93SStefano Zampini   }
7748b0f5fe93SStefano Zampini 
7749b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7750b0f5fe93SStefano Zampini     PetscBool ispreonly;
7751b0f5fe93SStefano Zampini 
7752b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7753b0f5fe93SStefano Zampini       PetscBool isnull;
7754b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7755bef83e63SStefano Zampini       if (isnull) {
7756b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7757b0f5fe93SStefano Zampini       }
7758bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7759b0f5fe93SStefano Zampini     }
7760b0f5fe93SStefano Zampini     /* setup coarse ksp */
7761b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7762cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7763cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
77646e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7765c8587f34SStefano Zampini       KSP       check_ksp;
77662b510759SStefano Zampini       KSPType   check_ksp_type;
7767c8587f34SStefano Zampini       PC        check_pc;
77686e683305SStefano Zampini       Vec       check_vec,coarse_vec;
77696a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
77702b510759SStefano Zampini       PetscInt  its;
77716e683305SStefano Zampini       PetscBool compute_eigs;
77726e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
77736e683305SStefano Zampini       PetscInt  neigs;
77748e185a42SStefano Zampini       const char *prefix;
7775c8587f34SStefano Zampini 
77762b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
77776e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7778422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
777923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7780f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7781e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7782e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7783e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
77842b510759SStefano Zampini       if (ispreonly) {
77852b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
77866e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
77872b510759SStefano Zampini       } else {
7788cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
77896e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7790c8587f34SStefano Zampini       }
7791c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
77926e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
77936e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
77946e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7795a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7796a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7797a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7798a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7799c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7800c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7801c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7802c8587f34SStefano Zampini       /* create random vec */
78032701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7804c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
78056e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7806c8587f34SStefano Zampini       /* solve coarse problem */
78076e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7808cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
78096e683305SStefano Zampini       if (compute_eigs) {
7810854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7811854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
78126e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
78131ae86dd6SStefano Zampini         if (neigs) {
78146e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
78156e683305SStefano Zampini           lambda_min = eigs_r[0];
78166e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
78172701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
78182701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7819cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7820cbcc2c2aSStefano Zampini             }
7821c8587f34SStefano Zampini           }
7822c8587f34SStefano Zampini         }
78231ae86dd6SStefano Zampini       }
7824cbcc2c2aSStefano Zampini 
7825c8587f34SStefano Zampini       /* check coarse problem residual error */
78266e683305SStefano Zampini       if (pcbddc->dbg_flag) {
78276e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
78286e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
78296e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7830c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
78316e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
78326e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7833779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
78346e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
78356e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
78366e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
78376e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7838b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7839b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7840b0f5fe93SStefano Zampini         }
78416e683305SStefano Zampini         if (compute_eigs) {
78426e683305SStefano Zampini           PetscReal          lambda_max_s,lambda_min_s;
7843b03ebc13SStefano Zampini           KSPConvergedReason reason;
7844deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7845c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
7846b03ebc13SStefano Zampini           ierr = KSPGetConvergedReason(check_ksp,&reason);CHKERRQ(ierr);
78476e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
7848b03ebc13SStefano 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);
78496e683305SStefano Zampini           for (i=0;i<neigs;i++) {
78506e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7851c8587f34SStefano Zampini           }
78526e683305SStefano Zampini         }
78536e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
78546e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
78556e683305SStefano Zampini       }
7856e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
78572701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7858c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
78596e683305SStefano Zampini       if (compute_eigs) {
78606e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
78616e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7862c8587f34SStefano Zampini       }
78636e683305SStefano Zampini     }
78646e683305SStefano Zampini   }
7865bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7866cbcc2c2aSStefano Zampini   /* print additional info */
7867cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
78686e683305SStefano Zampini     /* waits until all processes reaches this point */
78696e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7870cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7871cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7872cbcc2c2aSStefano Zampini   }
7873cbcc2c2aSStefano Zampini 
78742b510759SStefano Zampini   /* free memory */
7875fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7876c8587f34SStefano Zampini   PetscFunctionReturn(0);
7877c8587f34SStefano Zampini }
7878674ae819SStefano Zampini 
7879f34684f1SStefano Zampini #undef __FUNCT__
7880f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7881f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7882f34684f1SStefano Zampini {
7883f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7884f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7885f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7886dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7887dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
788873be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7889dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7890f34684f1SStefano Zampini   PetscErrorCode ierr;
7891f34684f1SStefano Zampini 
7892f34684f1SStefano Zampini   PetscFunctionBegin;
7893f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
78946c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7895dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
78963bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7897dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7898dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
78996583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7900dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7901dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7902dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
79036c4ed002SBarry 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);
7904dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7905dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7906dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7907dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7908dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7909f34684f1SStefano Zampini 
7910f34684f1SStefano Zampini   /* check numbering */
7911f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7912019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7913dc456d91SStefano Zampini     PetscInt    i;
7914b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7915f34684f1SStefano Zampini 
7916f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7917f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7918f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
79191575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7920019a44ceSStefano Zampini     /* counter */
7921019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7922019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7923019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7924019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7925019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7926019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7927f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7928f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7929727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7930f34684f1SStefano Zampini     }
7931f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7932f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7933f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7934e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7935e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7936e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7937e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7938f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7939019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7940f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7941019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
79422c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
794375c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7944b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
79452c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
79462c66d082SStefano 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);
7947f34684f1SStefano Zampini       }
7948f34684f1SStefano Zampini     }
7949019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7950b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7951f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7952f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7953f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7954f34684f1SStefano Zampini     }
7955f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7956f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7957e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7958e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7959f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7960f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7961b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7962ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7963ca8b9ea9SStefano Zampini 
7964ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
79653bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7966f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7967f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7968f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7969f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
79704bc2dc4bSStefano 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);
7971f34684f1SStefano Zampini       }
7972f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7973ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7974f34684f1SStefano Zampini     }
7975f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
79761575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7977302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7978f34684f1SStefano Zampini   }
79798bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7980f34684f1SStefano Zampini   /* get back data */
7981f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7982f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7983674ae819SStefano Zampini   PetscFunctionReturn(0);
7984674ae819SStefano Zampini }
7985674ae819SStefano Zampini 
7986e456f2a8SStefano Zampini #undef __FUNCT__
7987e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7988a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7989e456f2a8SStefano Zampini {
7990e456f2a8SStefano Zampini   IS             localis_t;
7991a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7992e456f2a8SStefano Zampini   PetscScalar    *vals;
7993e456f2a8SStefano Zampini   PetscErrorCode ierr;
7994e456f2a8SStefano Zampini 
7995e456f2a8SStefano Zampini   PetscFunctionBegin;
7996a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7997e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7998854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7999e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
8000e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8001a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
8002a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
80031035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
8004a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
80051035eff8SStefano Zampini   }
8006a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
8007e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
8008e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
8009a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
8010a7dc3881SStefano Zampini   /* now compute set in local ordering */
8011a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8012a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8013a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8014a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
8015a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8016ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8017e456f2a8SStefano Zampini       lsize++;
8018e456f2a8SStefano Zampini     }
8019e456f2a8SStefano Zampini   }
8020854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
8021a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
8022ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
8023e456f2a8SStefano Zampini       idxs[lsize++] = i;
8024e456f2a8SStefano Zampini     }
8025e456f2a8SStefano Zampini   }
8026a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
8027a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
8028e456f2a8SStefano Zampini   *localis = localis_t;
8029e456f2a8SStefano Zampini   PetscFunctionReturn(0);
8030e456f2a8SStefano Zampini }
8031906d46d4SStefano Zampini 
8032b96c3477SStefano Zampini #undef __FUNCT__
8033b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
803408122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
8035b96c3477SStefano Zampini {
8036a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8037b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8038b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
8039a64f4aa4SStefano Zampini   Mat                 S_j;
8040b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
8041b96c3477SStefano Zampini   PetscBool           free_used_adj;
8042b96c3477SStefano Zampini   PetscErrorCode      ierr;
8043b96c3477SStefano Zampini 
8044b96c3477SStefano Zampini   PetscFunctionBegin;
8045b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
8046b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
804708122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
8048b96c3477SStefano Zampini     used_xadj = NULL;
8049b96c3477SStefano Zampini     used_adjncy = NULL;
8050b96c3477SStefano Zampini   } else {
805108122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
805208122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
805308122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
805408122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
8055b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
8056b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
8057b96c3477SStefano Zampini     } else {
80582fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
8059b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
8060b96c3477SStefano Zampini       PetscInt       nvtxs;
8061b96c3477SStefano Zampini 
80622fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
80632fffb893SStefano Zampini       if (flg_row) {
8064b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
8065b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
8066b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
8067b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
80682fffb893SStefano Zampini       } else {
80692fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
80702fffb893SStefano Zampini         used_xadj = NULL;
80712fffb893SStefano Zampini         used_adjncy = NULL;
80722fffb893SStefano Zampini       }
80732fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
8074b96c3477SStefano Zampini     }
8075b96c3477SStefano Zampini   }
8076d5574798SStefano Zampini 
8077d5574798SStefano Zampini   /* setup sub_schurs data */
8078a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8079df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
8080df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
8081a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
808291af6908SStefano 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);
8083a64f4aa4SStefano Zampini   } else {
80846816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
80854d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
8086a3df083aSStefano Zampini     PetscInt  benign_n;
808772b8c272SStefano Zampini     Mat       change = NULL;
80889d54b7f4SStefano Zampini     Vec       scaling = NULL;
808972b8c272SStefano Zampini     IS        change_primal = NULL;
8090a3df083aSStefano Zampini 
80915feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
80925feab87aSStefano Zampini       PetscInt n_vertices;
80935feab87aSStefano Zampini 
80945feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
80952034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
80965feab87aSStefano Zampini     }
809704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
809804708bb6SStefano Zampini     if (!isseqaij) {
809904708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
810004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
810104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
810204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
810304708bb6SStefano Zampini       } else {
8104511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
810504708bb6SStefano Zampini       }
810604708bb6SStefano Zampini     }
8107a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
8108a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
8109ca92afb2SStefano Zampini     } else {
8110a3df083aSStefano Zampini       benign_n = 0;
8111ca92afb2SStefano Zampini     }
8112b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
8113b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
8114b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
811572b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
811622db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
8117b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
811822db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
8119b7ab4a40SStefano Zampini     }
8120b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
8121b7ab4a40SStefano 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 */
8122b7ab4a40SStefano Zampini     if (need_change) {
812388c03ad3SStefano Zampini       PC_IS   *pcisf;
812488c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
812588c03ad3SStefano Zampini       PC      pcf;
812688c03ad3SStefano Zampini 
8127e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
812888c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
812988c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
813088c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
813188c03ad3SStefano Zampini       /* hacks */
813288c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
813372b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
813472b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
813572b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
813672b8c272SStefano Zampini       pcisf->n = pcis->n;
813772b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
813888c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
813988c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
814088c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
814188c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
814288c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
814388c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
814472b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
814588c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
814688c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
814772b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
814872b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
814972b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
815072b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
815172b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
815288c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
815372b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
815488c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
815588c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
815688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
815788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
815888c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
815988c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
816088c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
816188c03ad3SStefano Zampini     }
81629d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
816391af6908SStefano 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);
816472b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
816572b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
8166ca92afb2SStefano Zampini   }
8167d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8168b96c3477SStefano Zampini 
8169b96c3477SStefano Zampini   /* free adjacency */
8170b96c3477SStefano Zampini   if (free_used_adj) {
8171b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
8172b96c3477SStefano Zampini   }
8173b96c3477SStefano Zampini   PetscFunctionReturn(0);
8174b96c3477SStefano Zampini }
8175b96c3477SStefano Zampini 
8176b96c3477SStefano Zampini #undef __FUNCT__
8177b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
817808122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
8179b96c3477SStefano Zampini {
8180b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8181b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8182b96c3477SStefano Zampini   PCBDDCGraph         graph;
8183b96c3477SStefano Zampini   PetscErrorCode      ierr;
8184b96c3477SStefano Zampini 
8185b96c3477SStefano Zampini   PetscFunctionBegin;
8186b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
818708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
81883301b35fSStefano Zampini     IS       verticesIS,verticescomm;
81893301b35fSStefano Zampini     PetscInt vsize,*idxs;
8190b96c3477SStefano Zampini 
8191b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
81923301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
81933301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
81943301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
81953301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
8196c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
8197b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
8198be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
8199441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
82003301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
8201b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
8202b96c3477SStefano Zampini   } else {
8203b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
8204b96c3477SStefano Zampini   }
8205e4d548c7SStefano Zampini   /* print some info */
82065c643e28SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) {
8207e4d548c7SStefano Zampini     IS       vertices;
8208e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
8209c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
8210e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8211e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
8212e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8213e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
8214e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
8215e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
8216e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
8217e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
8218e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
8219c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
8220e4d548c7SStefano Zampini   }
8221b96c3477SStefano Zampini 
8222b96c3477SStefano Zampini   /* sub_schurs init */
8223b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
8224b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
8225b334f244SStefano Zampini   }
82268b6046baSStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
8227a64f4aa4SStefano Zampini 
8228b96c3477SStefano Zampini   /* free graph struct */
822908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
8230b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
8231b96c3477SStefano Zampini   }
8232b96c3477SStefano Zampini   PetscFunctionReturn(0);
8233b96c3477SStefano Zampini }
8234fa34dd3eSStefano Zampini 
8235fa34dd3eSStefano Zampini #undef __FUNCT__
8236fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
8237fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
8238fa34dd3eSStefano Zampini {
8239fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
8240fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
8241fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
8242fa34dd3eSStefano Zampini 
8243fa34dd3eSStefano Zampini   PetscFunctionBegin;
8244fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
8245fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
82464f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
8247fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
82484f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
824975c01103SStefano Zampini     PetscReal      norm;
8250fa34dd3eSStefano Zampini     PetscInt       i;
8251fa34dd3eSStefano Zampini 
8252fa34dd3eSStefano Zampini     /* B0 and B0_B */
8253fa34dd3eSStefano Zampini     if (zerodiag) {
8254fa34dd3eSStefano Zampini       IS       dummy;
8255fa34dd3eSStefano Zampini 
82564f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
82574f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
8258fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
8259fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
8260fa34dd3eSStefano Zampini     }
8261fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
8262fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
8263fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
8264fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8265fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8266fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8267fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8268fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
8269fa34dd3eSStefano Zampini     /* S_j */
8270fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
8271fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
8272fa34dd3eSStefano Zampini 
8273fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
8274fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
8275fa34dd3eSStefano Zampini     /* continuous in primal space */
8276fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
8277fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8278fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8279fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
82804f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
82814f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
8282fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8283fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8284fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8285fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8286fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8287fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8288fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
8289fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
8290fa34dd3eSStefano Zampini 
8291fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
8292fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
8293fa34dd3eSStefano Zampini     /* local with Schur */
8294fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
8295fa34dd3eSStefano Zampini     if (zerodiag) {
8296fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
82974f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
8298fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8299fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
8300fa34dd3eSStefano Zampini     }
8301fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
8302fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8303fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8304fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8305fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8306fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
8307fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
8308fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8309fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
8310fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8311fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8312fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8313fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8314fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8315fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
8316fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
8317fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
8318fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
8319fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
8320fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
8321fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8322fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8323fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
8324fa34dd3eSStefano Zampini     if (zerodiag) {
8325fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
8326fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
83274f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
8328fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
8329fa34dd3eSStefano Zampini     }
8330fa34dd3eSStefano Zampini     /* BDDC */
8331fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
8332fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
8333fa34dd3eSStefano Zampini 
8334fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
8335fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
8336fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
8337fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
83384f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
83394f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
8340fa34dd3eSStefano Zampini     }
83414f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
8342fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
8343fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
8344fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
8345fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
8346fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
8347fa34dd3eSStefano Zampini   }
8348fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
8349fa34dd3eSStefano Zampini }
83501e0482f5SStefano Zampini 
83511e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
83521e0482f5SStefano Zampini #undef __FUNCT__
83531e0482f5SStefano Zampini #define __FUNCT__ "MatMPIAIJRestrict"
83541e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B)
83551e0482f5SStefano Zampini {
83561e0482f5SStefano Zampini   Mat            At;
83571e0482f5SStefano Zampini   IS             rows;
83581e0482f5SStefano Zampini   PetscInt       rst,ren;
83591e0482f5SStefano Zampini   PetscErrorCode ierr;
83601e0482f5SStefano Zampini   PetscLayout    rmap;
83611e0482f5SStefano Zampini 
83621e0482f5SStefano Zampini   PetscFunctionBegin;
83631e0482f5SStefano Zampini   rst = ren = 0;
83641e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
83651e0482f5SStefano Zampini     ierr = PetscLayoutCreate(ccomm,&rmap);CHKERRQ(ierr);
83661e0482f5SStefano Zampini     ierr = PetscLayoutSetSize(rmap,A->rmap->N);CHKERRQ(ierr);
83671e0482f5SStefano Zampini     ierr = PetscLayoutSetBlockSize(rmap,1);CHKERRQ(ierr);
83681e0482f5SStefano Zampini     ierr = PetscLayoutSetUp(rmap);CHKERRQ(ierr);
83691e0482f5SStefano Zampini     ierr = PetscLayoutGetRange(rmap,&rst,&ren);CHKERRQ(ierr);
83701e0482f5SStefano Zampini   }
8371e07686f2SStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows);CHKERRQ(ierr);
83721e0482f5SStefano Zampini   ierr = MatGetSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
83731e0482f5SStefano Zampini   ierr = ISDestroy(&rows);CHKERRQ(ierr);
83741e0482f5SStefano Zampini 
83751e0482f5SStefano Zampini   if (ccomm != MPI_COMM_NULL) {
83761e0482f5SStefano Zampini     Mat_MPIAIJ *a,*b;
83771e0482f5SStefano Zampini     IS         from,to;
83781e0482f5SStefano Zampini     Vec        gvec;
83791e0482f5SStefano Zampini     PetscInt   lsize;
83801e0482f5SStefano Zampini 
83811e0482f5SStefano Zampini     ierr = MatCreate(ccomm,B);CHKERRQ(ierr);
83821e0482f5SStefano Zampini     ierr = MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N);CHKERRQ(ierr);
83831e0482f5SStefano Zampini     ierr = MatSetType(*B,MATAIJ);CHKERRQ(ierr);
83841e0482f5SStefano Zampini     ierr = PetscLayoutDestroy(&((*B)->rmap));CHKERRQ(ierr);
83851e0482f5SStefano Zampini     ierr = PetscLayoutSetUp((*B)->cmap);CHKERRQ(ierr);
83861e0482f5SStefano Zampini     a    = (Mat_MPIAIJ*)At->data;
83871e0482f5SStefano Zampini     b    = (Mat_MPIAIJ*)(*B)->data;
83881e0482f5SStefano Zampini     ierr = MPI_Comm_size(ccomm,&b->size);CHKERRQ(ierr);
83891e0482f5SStefano Zampini     ierr = MPI_Comm_rank(ccomm,&b->rank);CHKERRQ(ierr);
83901e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->A);CHKERRQ(ierr);
83911e0482f5SStefano Zampini     ierr = PetscObjectReference((PetscObject)a->B);CHKERRQ(ierr);
83921e0482f5SStefano Zampini     b->A = a->A;
83931e0482f5SStefano Zampini     b->B = a->B;
83941e0482f5SStefano Zampini 
83951e0482f5SStefano Zampini     b->donotstash      = a->donotstash;
83961e0482f5SStefano Zampini     b->roworiented     = a->roworiented;
83971e0482f5SStefano Zampini     b->rowindices      = 0;
83981e0482f5SStefano Zampini     b->rowvalues       = 0;
83991e0482f5SStefano Zampini     b->getrowactive    = PETSC_FALSE;
84001e0482f5SStefano Zampini 
84011e0482f5SStefano Zampini     (*B)->rmap         = rmap;
84021e0482f5SStefano Zampini     (*B)->factortype   = A->factortype;
84031e0482f5SStefano Zampini     (*B)->assembled    = PETSC_TRUE;
84041e0482f5SStefano Zampini     (*B)->insertmode   = NOT_SET_VALUES;
84051e0482f5SStefano Zampini     (*B)->preallocated = PETSC_TRUE;
84061e0482f5SStefano Zampini 
84071e0482f5SStefano Zampini     if (a->colmap) {
84081e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE)
84091e0482f5SStefano Zampini       ierr = PetscTableCreateCopy(a->colmap,&b->colmap);CHKERRQ(ierr);
84101e0482f5SStefano Zampini #else
84111e0482f5SStefano Zampini       ierr = PetscMalloc1(At->cmap->N,&b->colmap);CHKERRQ(ierr);
84121e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
84131e0482f5SStefano Zampini       ierr = PetscMemcpy(b->colmap,a->colmap,At->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
84141e0482f5SStefano Zampini #endif
84151e0482f5SStefano Zampini     } else b->colmap = 0;
84161e0482f5SStefano Zampini     if (a->garray) {
84171e0482f5SStefano Zampini       PetscInt len;
84181e0482f5SStefano Zampini       len  = a->B->cmap->n;
84191e0482f5SStefano Zampini       ierr = PetscMalloc1(len+1,&b->garray);CHKERRQ(ierr);
84201e0482f5SStefano Zampini       ierr = PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt));CHKERRQ(ierr);
84211e0482f5SStefano Zampini       if (len) { ierr = PetscMemcpy(b->garray,a->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
84221e0482f5SStefano Zampini     } else b->garray = 0;
84231e0482f5SStefano Zampini 
84241e0482f5SStefano Zampini     ierr    = PetscObjectReference((PetscObject)a->lvec);CHKERRQ(ierr);
84251e0482f5SStefano Zampini     b->lvec = a->lvec;
84261e0482f5SStefano Zampini     ierr    = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec);CHKERRQ(ierr);
84271e0482f5SStefano Zampini 
84281e0482f5SStefano Zampini     /* cannot use VecScatterCopy */
84291e0482f5SStefano Zampini     ierr = VecGetLocalSize(b->lvec,&lsize);CHKERRQ(ierr);
84301e0482f5SStefano Zampini     ierr = ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
84311e0482f5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to);CHKERRQ(ierr);
84321e0482f5SStefano Zampini     ierr = MatCreateVecs(*B,&gvec,NULL);CHKERRQ(ierr);
84331e0482f5SStefano Zampini     ierr = VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx);CHKERRQ(ierr);
84341e0482f5SStefano Zampini     ierr = PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx);CHKERRQ(ierr);
84351e0482f5SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
84361e0482f5SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
84371e0482f5SStefano Zampini     ierr = VecDestroy(&gvec);CHKERRQ(ierr);
84381e0482f5SStefano Zampini   }
84391e0482f5SStefano Zampini   ierr = MatDestroy(&At);CHKERRQ(ierr);
84401e0482f5SStefano Zampini   PetscFunctionReturn(0);
84411e0482f5SStefano Zampini }
8442