xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 8af8fcf9e4fff1f745ef0b26ae02869b6d857906)
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 
7a13144ffSStefano Zampini /* returns B s.t. range(B) _|_ range(A) */
8a13144ffSStefano Zampini #undef __FUNCT__
9a13144ffSStefano Zampini #define __FUNCT__ "MatDense_OrthogonalComplement"
10a13144ffSStefano Zampini PetscErrorCode MatDense_OrthogonalComplement(Mat A, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B)
11a13144ffSStefano Zampini {
12a13144ffSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
13a13144ffSStefano Zampini   PetscScalar    *uwork,*data,*U, ds = 0.;
14a13144ffSStefano Zampini   PetscReal      *sing;
15a13144ffSStefano Zampini   PetscBLASInt   bM,bN,lwork,lierr,di = 1;
16a13144ffSStefano Zampini   PetscInt       ulw,i,nr,nc,n;
17a13144ffSStefano Zampini   PetscErrorCode ierr;
18a13144ffSStefano Zampini 
19a13144ffSStefano Zampini   PetscFunctionBegin;
20a13144ffSStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
21a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAPACK _GESVD not available");
22a13144ffSStefano Zampini #endif
23a13144ffSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
24a13144ffSStefano Zampini   if (!nr || !nc) PetscFunctionReturn(0);
25a13144ffSStefano Zampini 
26a13144ffSStefano Zampini   /* workspace */
27a13144ffSStefano Zampini   if (!work) {
28a13144ffSStefano Zampini     ulw  = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc));
29a13144ffSStefano Zampini     ierr = PetscMalloc1(ulw,&uwork);
30a13144ffSStefano Zampini   } else {
31a13144ffSStefano Zampini     ulw   = lw;
32a13144ffSStefano Zampini     uwork = work;
33a13144ffSStefano Zampini   }
34a13144ffSStefano Zampini   n = PetscMin(nr,nc);
35a13144ffSStefano Zampini   if (!rwork) {
36a13144ffSStefano Zampini     ierr = PetscMalloc1(n,&sing);CHKERRQ(ierr);
37a13144ffSStefano Zampini   } else {
38a13144ffSStefano Zampini     sing = rwork;
39a13144ffSStefano Zampini   }
40a13144ffSStefano Zampini 
41a13144ffSStefano Zampini   /* SVD */
42a13144ffSStefano Zampini   ierr = PetscMalloc1(nr*nr,&U);CHKERRQ(ierr);
43a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nr,&bM);CHKERRQ(ierr);
44a13144ffSStefano Zampini   ierr = PetscBLASIntCast(nc,&bN);CHKERRQ(ierr);
45a13144ffSStefano Zampini   ierr = PetscBLASIntCast(ulw,&lwork);CHKERRQ(ierr);
46a13144ffSStefano Zampini   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
47a13144ffSStefano Zampini   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
48a13144ffSStefano Zampini   PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr));
49a13144ffSStefano Zampini   ierr = PetscFPTrapPop();CHKERRQ(ierr);
50a13144ffSStefano Zampini   if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
51a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(A,&data);CHKERRQ(ierr);
52a13144ffSStefano Zampini   for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break;
53a13144ffSStefano Zampini   if (!rwork) {
54a13144ffSStefano Zampini     ierr = PetscFree(sing);CHKERRQ(ierr);
55a13144ffSStefano Zampini   }
56a13144ffSStefano Zampini   if (!work) {
57a13144ffSStefano Zampini     ierr = PetscFree(uwork);CHKERRQ(ierr);
58a13144ffSStefano Zampini   }
59a13144ffSStefano Zampini   /* create B */
60a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B);CHKERRQ(ierr);
61a13144ffSStefano Zampini   ierr = MatDenseGetArray(*B,&data);CHKERRQ(ierr);
62a13144ffSStefano Zampini   ierr = PetscMemcpy(data,U+nr*i,(nr-i)*nr*sizeof(PetscScalar));CHKERRQ(ierr);
63a13144ffSStefano Zampini   ierr = MatDenseRestoreArray(*B,&data);CHKERRQ(ierr);
64a13144ffSStefano Zampini   ierr = PetscFree(U);CHKERRQ(ierr);
65a13144ffSStefano Zampini #else
66a13144ffSStefano Zampini   PetscFunctionBegin;
67a13144ffSStefano Zampini   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for complexes");
68a13144ffSStefano Zampini #endif
69a13144ffSStefano Zampini   PetscFunctionReturn(0);
70a13144ffSStefano Zampini }
71a13144ffSStefano Zampini 
72a13144ffSStefano Zampini #undef __FUNCT__
73a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCComputeNedelecChangeEdge"
74a13144ffSStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, Mat* Gins, Mat* GKins, PetscScalar *work, PetscReal *rwork)
75a13144ffSStefano Zampini {
76a13144ffSStefano Zampini   PetscErrorCode ierr;
77a13144ffSStefano Zampini   Mat            GE,GEd;
78a13144ffSStefano Zampini   PetscInt       rsize,csize,esize;
79a13144ffSStefano Zampini   PetscScalar    *ptr;
80a13144ffSStefano Zampini 
81a13144ffSStefano Zampini   PetscFunctionBegin;
82a13144ffSStefano Zampini   ierr = ISGetSize(edge,&esize);CHKERRQ(ierr);
83c3c0e390SStefano Zampini   if (!esize) PetscFunctionReturn(0);
84a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
85a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
86a13144ffSStefano Zampini 
87a13144ffSStefano Zampini   /* gradients */
88a13144ffSStefano Zampini   ptr  = work + 5*esize;
89a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
90a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
91a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
92a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
93a13144ffSStefano Zampini 
94a13144ffSStefano Zampini   /* constants */
95a13144ffSStefano Zampini   ptr += rsize*csize;
96a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
97a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
98a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
99a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
100a13144ffSStefano Zampini   ierr = MatDense_OrthogonalComplement(GEd,5*esize,work,rwork,GKins);CHKERRQ(ierr);
101a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
102a13144ffSStefano Zampini   PetscFunctionReturn(0);
103a13144ffSStefano Zampini }
104a13144ffSStefano Zampini 
105a13144ffSStefano Zampini #undef __FUNCT__
106a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCNedelecSupport"
107a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
108a13144ffSStefano Zampini {
109a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
110a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
1110569b399SStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit;
112a13144ffSStefano Zampini   MatNullSpace           nnsp;
113a13144ffSStefano Zampini   Vec                    tvec,*quads;
114a13144ffSStefano Zampini   PetscSF                sfv;
115c2151214SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g;
116a13144ffSStefano Zampini   MPI_Comm               comm;
117c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
118c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
119c2151214SStefano Zampini   PetscBT                btv,bte,btvc,btb,btvcand,btvi,btee;
120a13144ffSStefano Zampini   PetscScalar            *vals,*work;
121a13144ffSStefano Zampini   PetscReal              *rwork;
122a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
123c2151214SStefano Zampini   PetscInt               ne,nv,Lv,order,n,field;
124a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
125a13144ffSStefano Zampini   PetscInt               i,j,extmem,cum,maxsize,rst,nee,nquads=2;
126a13144ffSStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*emarks,*vmarks,*gidxs;
127a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
128c2151214SStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming;
129a13144ffSStefano Zampini   PetscErrorCode         ierr;
130a13144ffSStefano Zampini 
131a13144ffSStefano Zampini   PetscFunctionBegin;
132a13144ffSStefano Zampini   /* test variable order code and print debug info TODO: to be removed */
133a13144ffSStefano Zampini   print = PETSC_FALSE;
134a13144ffSStefano Zampini   ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_print_nedelec",&print,NULL);CHKERRQ(ierr);
135a13144ffSStefano Zampini   ierr = PetscOptionsGetInt(NULL,NULL,"-pc_bddc_nedelec_order",&pcbddc->nedorder,NULL);CHKERRQ(ierr);
136a13144ffSStefano Zampini 
137a13144ffSStefano Zampini   /* Return to caller if there are no edges in the decomposition */
138a13144ffSStefano Zampini   ierr   = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
139a13144ffSStefano Zampini   ierr   = MatGetLocalToGlobalMapping(pc->pmat,&el2g,NULL);CHKERRQ(ierr);
140c2151214SStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(el2g,&n);CHKERRQ(ierr);
141a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
142a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
143c2151214SStefano Zampini   for (i=0;i<n;i++) {
144a13144ffSStefano Zampini     if (PetscRealPart(vals[i]) > 2.) {
145a13144ffSStefano Zampini       lrc[0] = PETSC_TRUE;
146a13144ffSStefano Zampini       break;
147a13144ffSStefano Zampini     }
148a13144ffSStefano Zampini   }
149a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
150a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
151a13144ffSStefano Zampini   if (!lrc[1]) PetscFunctionReturn(0);
152a13144ffSStefano Zampini 
153c2151214SStefano Zampini   /* Get discrete gradient
154c2151214SStefano Zampini      If it is defined for a subset of dofs, assumes G is given in global ordering for all the dofs */
155a13144ffSStefano Zampini   G          = pcbddc->discretegradient;
156a13144ffSStefano Zampini   order      = pcbddc->nedorder;
157a13144ffSStefano Zampini   conforming = pcbddc->conforming;
158c2151214SStefano Zampini   field      = pcbddc->nedfield;
159c2151214SStefano 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);
160c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field > -1) {
161c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
162c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
163c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
164c2151214SStefano Zampini   } else {
165c2151214SStefano Zampini     PetscBool testnedfield = PETSC_FALSE;
166c2151214SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field",&testnedfield,NULL);CHKERRQ(ierr);
167c2151214SStefano Zampini     if (!testnedfield) {
168c2151214SStefano Zampini       ne            = n;
169c2151214SStefano Zampini       nedfieldlocal = NULL;
170c2151214SStefano Zampini     } else {
171c2151214SStefano Zampini       /* ierr = ISCreateStride(comm,n,0,1,&nedfieldlocal);CHKERRQ(ierr); */
172c2151214SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
173c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
174c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
175c2151214SStefano Zampini       for (i=0;i<n;i++) matis->sf_leafdata[i] = 1;
176c2151214SStefano Zampini       ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
177c2151214SStefano Zampini       ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
178c2151214SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
179c2151214SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
180c2151214SStefano Zampini       for (i=0,cum=0;i<n;i++) {
181c2151214SStefano Zampini         if (matis->sf_leafdata[i] > 1) {
182c2151214SStefano Zampini           matis->sf_leafdata[cum++] = i;
183c2151214SStefano Zampini         }
184c2151214SStefano Zampini       }
185c2151214SStefano Zampini       ierr = ISCreateGeneral(comm,cum,matis->sf_leafdata,PETSC_COPY_VALUES,&nedfieldlocal);CHKERRQ(ierr);
186c2151214SStefano Zampini       ierr = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
187c2151214SStefano Zampini     }
188c2151214SStefano Zampini   }
189a13144ffSStefano Zampini 
190c2151214SStefano Zampini   if (nedfieldlocal) { /* merge with previous code when testing is done */
191c2151214SStefano Zampini     IS is;
192c2151214SStefano Zampini 
193c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
194c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
195c2151214SStefano Zampini     /* need to map from the local Nedelec field to global numbering */
196c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,nedfieldlocal,&is);CHKERRQ(ierr);
197c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&el2g);CHKERRQ(ierr);
198c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
199c2151214SStefano Zampini   } else {
200c2151214SStefano Zampini     ierr = PetscObjectReference((PetscObject)el2g);CHKERRQ(ierr);
201c2151214SStefano Zampini     fl2g = NULL;
202c2151214SStefano Zampini   }
203a13144ffSStefano Zampini 
204a13144ffSStefano Zampini   /* Sanity checks */
205a13144ffSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
206a13144ffSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
207a13144ffSStefano 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);
208a13144ffSStefano Zampini 
209a13144ffSStefano Zampini   /* Drop connections for interior edges (this modifies G) */
210c2151214SStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
211c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
212c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
213c2151214SStefano Zampini   if (nedfieldlocal) {
214c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
215c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
216c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
217c2151214SStefano Zampini   } else {
218c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
219c2151214SStefano Zampini   }
220c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
221c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
222c2151214SStefano Zampini   ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
223c2151214SStefano Zampini   for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
224c2151214SStefano Zampini     if (matis->sf_rootdata[i] < 2) {
225c2151214SStefano Zampini       matis->sf_rootdata[cum++] = i + rst;
226c2151214SStefano Zampini     }
227c2151214SStefano Zampini   }
228a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
229a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
230c2151214SStefano Zampini   ierr = MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL);CHKERRQ(ierr);
231a13144ffSStefano Zampini 
232a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
233a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
234a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
235a13144ffSStefano Zampini   ierr = MatGetSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
236a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
237a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
238a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
239a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
240a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
241a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
242a13144ffSStefano Zampini   if (print) {
243a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
244a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
245a13144ffSStefano Zampini   }
246a13144ffSStefano Zampini 
247a13144ffSStefano Zampini   /* SF for nodal communications */
248c2151214SStefano Zampini   ierr = MatGetLocalSize(G,NULL,&Lv);CHKERRQ(ierr);
249a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
250a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
251a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
252a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
253a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
254a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
255a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
256a13144ffSStefano Zampini   ierr = PetscMalloc2(nv,&sfvleaves,Lv,&sfvroots);CHKERRQ(ierr);
257a13144ffSStefano Zampini 
258a13144ffSStefano Zampini   /* Destroy temporary G created in MATIS format */
259a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
260a13144ffSStefano Zampini 
2610569b399SStefano Zampini   /* Save lG */
2620569b399SStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGinit);CHKERRQ(ierr);
2630569b399SStefano Zampini 
264a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
2654e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
2664e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
267a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
268a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
269a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
270c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
271a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
272a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
273a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
274c2151214SStefano Zampini     IS is;
275c2151214SStefano Zampini 
276c2151214SStefano Zampini     if (fl2g) {
277c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
278c2151214SStefano Zampini     } else {
279c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
280c2151214SStefano Zampini     }
281c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
282c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
283a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
284a13144ffSStefano Zampini       if (idxs[i] >= 0) {
285a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
286a13144ffSStefano Zampini       }
287a13144ffSStefano Zampini     }
288c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
289c2151214SStefano Zampini     if (fl2g) {
290c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
291c2151214SStefano Zampini     }
292a13144ffSStefano Zampini   }
293a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
294c2151214SStefano Zampini     IS is;
295c2151214SStefano Zampini 
296c2151214SStefano Zampini     if (fl2g) {
297c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
298c2151214SStefano Zampini     } else {
299c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
300c2151214SStefano Zampini     }
301c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
302c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
303a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
304a13144ffSStefano Zampini       if (idxs[i] >= 0) {
305a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
306a13144ffSStefano Zampini       }
307a13144ffSStefano Zampini     }
308c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
309c2151214SStefano Zampini     if (fl2g) {
310c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
311a13144ffSStefano Zampini     }
312c2151214SStefano Zampini   }
313c2151214SStefano Zampini 
314a13144ffSStefano Zampini   /* need to remove coarse faces' dofs to ensure the
315a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
316a13144ffSStefano Zampini   ierr = PetscCalloc1(ne,&marks);CHKERRQ(ierr);
31762b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
318a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
31962b0c6f7SStefano Zampini   for (i=1;i<n_neigh;i++)
32062b0c6f7SStefano Zampini     for (j=0;j<n_shared[i];j++)
32162b0c6f7SStefano Zampini       marks[shared[i][j]]++;
322a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
32362b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
32462b0c6f7SStefano Zampini     if (marks[i] > 1 || (marks[i] == 1 && PetscBTLookup(btb,i))) {
32562b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
32662b0c6f7SStefano Zampini     }
32762b0c6f7SStefano Zampini   }
32862b0c6f7SStefano Zampini 
32962b0c6f7SStefano Zampini   if (!conforming) {
33062b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
33162b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
33262b0c6f7SStefano Zampini   }
3334e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
334dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
33562b0c6f7SStefano Zampini   cum  = 0;
336a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
337dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
33862b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
339a13144ffSStefano Zampini       marks[cum++] = i;
340dec27d64SStefano Zampini       continue;
341dec27d64SStefano Zampini     }
342dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
34362b0c6f7SStefano Zampini     if (!conforming) {
34462b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
345a13144ffSStefano Zampini         marks[cum++] = i;
346a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
347a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
348a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
349a13144ffSStefano Zampini         }
35062b0c6f7SStefano Zampini       } else {
35162b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
35262b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
35362b0c6f7SStefano Zampini            - at most 2 endpoints
35462b0c6f7SStefano Zampini            - order-1 interior nodal dofs
35562b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
35662b0c6f7SStefano Zampini         */
35762b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
35862b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
35962b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
36062b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
36162b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
36262b0c6f7SStefano Zampini           if (nconn > order) ends++;
36362b0c6f7SStefano Zampini           else if (nconn == order) ints++;
36462b0c6f7SStefano Zampini           else undef++;
36562b0c6f7SStefano Zampini         }
36662b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
36762b0c6f7SStefano Zampini           marks[cum++] = i;
36862b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
36962b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
37062b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
37162b0c6f7SStefano Zampini           }
37262b0c6f7SStefano Zampini         }
37362b0c6f7SStefano Zampini       }
374a13144ffSStefano Zampini     }
375dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
376dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
377dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
378dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
379a13144ffSStefano Zampini     }
380dec27d64SStefano Zampini   }
38162b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
382dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
3834e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
38462b0c6f7SStefano Zampini   if (!conforming) {
38562b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
38662b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
38762b0c6f7SStefano Zampini   }
3884e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
389a13144ffSStefano Zampini   /* identify splitpoints and corner candidates: TODO variable order */
3904e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
391a13144ffSStefano Zampini   if (print) {
3924e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
3934e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
3944e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
395a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
396a13144ffSStefano Zampini   }
3970569b399SStefano Zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
398a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
399dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
400a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
401dec27d64SStefano Zampini     PetscInt ord = order, test = ii[i+1]-ii[i];
402dec27d64SStefano Zampini     if (!order) {
403dec27d64SStefano Zampini       PetscReal vorder = 0.;
404dec27d64SStefano Zampini 
405dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
406dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
407dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
408dec27d64SStefano Zampini       ord  = 1;
409dec27d64SStefano Zampini     }
410a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
411dec27d64SStefano 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);
412a13144ffSStefano Zampini #endif
413dec27d64SStefano Zampini     if (test >= 3*ord) { /* splitpoints */
414a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
415a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
416dec27d64SStefano Zampini     } else if (test == ord) {
417a13144ffSStefano Zampini       if (order == 1) {
418a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
419a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
420a13144ffSStefano Zampini       } else {
421a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
422a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
423a13144ffSStefano Zampini       }
424a13144ffSStefano Zampini     }
425a13144ffSStefano Zampini   }
426dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
427a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
428a13144ffSStefano Zampini 
429a13144ffSStefano Zampini   /* Get the local G^T explicitly */
4300569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
431a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
4324e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
433a13144ffSStefano Zampini 
4344e64d54eSstefano_zampini   /* Mark interior nodal dofs */
435a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
4364e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
437a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
438a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
4394e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
440a13144ffSStefano Zampini     }
441a13144ffSStefano Zampini   }
442a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
443a13144ffSStefano Zampini 
444a13144ffSStefano Zampini   /* communicate corners and splitpoints */
445a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
446a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
447a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
448a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
449a13144ffSStefano Zampini 
450a13144ffSStefano Zampini   if (print) {
451a13144ffSStefano Zampini     IS tbz;
452a13144ffSStefano Zampini 
453a13144ffSStefano Zampini     cum = 0;
454a13144ffSStefano Zampini     for (i=0;i<nv;i++)
455a13144ffSStefano Zampini       if (sfvleaves[i])
456a13144ffSStefano Zampini         vmarks[cum++] = i;
457a13144ffSStefano Zampini 
458a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
459a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
460a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
461a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
462a13144ffSStefano Zampini   }
463a13144ffSStefano Zampini 
464a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
465a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
466a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
467a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
468a13144ffSStefano Zampini 
4694e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
4704e64d54eSstefano_zampini      and interior nodal dofs */
471a13144ffSStefano Zampini   cum = 0;
472a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
473a13144ffSStefano Zampini     if (sfvleaves[i]) {
474a13144ffSStefano Zampini       vmarks[cum++] = i;
475a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
476a13144ffSStefano Zampini     }
4774e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
478a13144ffSStefano Zampini   }
4794e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
480a13144ffSStefano Zampini   if (print) {
481a13144ffSStefano Zampini     IS tbz;
482a13144ffSStefano Zampini 
483a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
4844e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
485a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
486a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
487a13144ffSStefano Zampini   }
488a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
489a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
490a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
491a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
492a13144ffSStefano Zampini 
493a13144ffSStefano Zampini   /* Recompute G */
494a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
495a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
496a13144ffSStefano Zampini   if (print) {
497a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
498a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
499a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
500a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
501a13144ffSStefano Zampini   }
502a13144ffSStefano Zampini 
503a13144ffSStefano Zampini   /* Get primal dofs (if any) */
504a13144ffSStefano Zampini   cum = 0;
505a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
506a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
507a13144ffSStefano Zampini   }
508c2151214SStefano Zampini   if (fl2g) {
509c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
510c2151214SStefano Zampini   }
511a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
512a13144ffSStefano Zampini   if (print) {
513a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
514a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
515a13144ffSStefano Zampini   }
516a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
517c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
518a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
519a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
520a13144ffSStefano Zampini 
521a13144ffSStefano Zampini   /* Compute edge connectivity */
522a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
523a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
524a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
525d904f53bSStefano Zampini   if (done && i && ii && jj) { /* when lG is empty, don't pass pointers */
526c2151214SStefano Zampini     if (fl2g) {
527c2151214SStefano Zampini       PetscBT   btf;
528c2151214SStefano Zampini       PetscInt  *iia,*jja,*iiu,*jju;
529c2151214SStefano Zampini       PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
530c2151214SStefano Zampini 
531c2151214SStefano Zampini       /* create CSR for all local dofs */
532c2151214SStefano Zampini       ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
533c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
534c2151214SStefano 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);
535c2151214SStefano Zampini         iiu = pcbddc->mat_graph->xadj;
536c2151214SStefano Zampini         jju = pcbddc->mat_graph->adjncy;
537c2151214SStefano Zampini       } else if (pcbddc->use_local_adj) {
538c2151214SStefano Zampini         rest = PETSC_TRUE;
539c2151214SStefano Zampini         ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
540c2151214SStefano Zampini       } else {
541c2151214SStefano Zampini         free   = PETSC_TRUE;
542c2151214SStefano Zampini         ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
543c2151214SStefano Zampini         iiu[0] = 0;
544c2151214SStefano Zampini         for (i=0;i<n;i++) {
545c2151214SStefano Zampini           iiu[i+1] = i+1;
546c2151214SStefano Zampini           jju[i]   = -1;
547d904f53bSStefano Zampini         }
548c2151214SStefano Zampini       }
549c2151214SStefano Zampini 
550c2151214SStefano Zampini       /* import sizes of CSR */
551c2151214SStefano Zampini       iia[0] = 0;
552c2151214SStefano Zampini       for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
553c2151214SStefano Zampini 
554c2151214SStefano Zampini       /* overwrite entries corresponding to the Nedelec field */
555c2151214SStefano Zampini       ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
556c2151214SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
557c2151214SStefano Zampini       for (i=0;i<ne;i++) {
558c2151214SStefano Zampini         ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
559c2151214SStefano Zampini         iia[idxs[i]+1] = ii[i+1]-ii[i];
560c2151214SStefano Zampini       }
561c2151214SStefano Zampini 
562c2151214SStefano Zampini       /* iia in CSR */
563c2151214SStefano Zampini       for (i=0;i<n;i++) iia[i+1] += iia[i];
564c2151214SStefano Zampini 
565c2151214SStefano Zampini       /* jja in CSR */
566c2151214SStefano Zampini       ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
567c2151214SStefano Zampini       for (i=0;i<n;i++)
568c2151214SStefano Zampini         if (!PetscBTLookup(btf,i))
569c2151214SStefano Zampini           for (j=0;j<iiu[i+1]-iiu[i];j++)
570c2151214SStefano Zampini             jja[iia[i]+j] = jju[iiu[i]+j];
571c2151214SStefano Zampini 
572c2151214SStefano Zampini       /* map edge dofs connectivity */
573c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
574c2151214SStefano Zampini       for (i=0;i<ne;i++) {
575c2151214SStefano Zampini         PetscInt e = idxs[i];
576c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
577c2151214SStefano Zampini       }
578c2151214SStefano Zampini 
579c2151214SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
580c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
581c2151214SStefano Zampini       if (rest) {
582c2151214SStefano Zampini         ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
583c2151214SStefano Zampini       }
584c2151214SStefano Zampini       if (free) {
585c2151214SStefano Zampini         ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
586c2151214SStefano Zampini       }
587c2151214SStefano Zampini       ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
588c2151214SStefano Zampini     } else {
589c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
590c2151214SStefano Zampini     }
591c2151214SStefano Zampini   }
592c2151214SStefano Zampini 
593a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
594a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
595a13144ffSStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
596a13144ffSStefano Zampini 
597a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
598a13144ffSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
599c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
600a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
601a13144ffSStefano Zampini 
602c2151214SStefano Zampini   if (fl2g) {
603c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
604c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
605c2151214SStefano Zampini     for (i=0;i<nee;i++) {
606c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
607c2151214SStefano Zampini     }
608c2151214SStefano Zampini   } else {
609c2151214SStefano Zampini     eedges  = alleedges;
610c2151214SStefano Zampini     primals = allprimals;
611c2151214SStefano Zampini   }
612c2151214SStefano Zampini 
613a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
614a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
615c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
616c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
617c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
618c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
619c2151214SStefano Zampini   if (print) {
620c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
621c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
622c2151214SStefano Zampini   }
623c2151214SStefano Zampini 
624c2151214SStefano Zampini   maxsize = 0;
625a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
626a13144ffSStefano Zampini     PetscInt size,mark = i+1;
627a13144ffSStefano Zampini 
628a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
629a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
630a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
631a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
632a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
633a13144ffSStefano Zampini   }
634a13144ffSStefano Zampini 
635a13144ffSStefano Zampini   /* Find coarse edge endpoints */
636a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
637a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
638a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
639a13144ffSStefano Zampini     PetscInt mark = i+1,size;
640a13144ffSStefano Zampini 
641a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
642a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
643a13144ffSStefano Zampini     if (print) {
644a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
645a13144ffSStefano Zampini       ISView(eedges[i],NULL);
646a13144ffSStefano Zampini     }
647a13144ffSStefano Zampini     for (j=0;j<size;j++) {
648a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
649a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
650a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
651a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
652a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
653a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
654a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
655a13144ffSStefano Zampini           PetscInt  k2;
656a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
657a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
658c2151214SStefano 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]));
659c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
660c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
661c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
662a13144ffSStefano Zampini               corner = PETSC_TRUE;
663a13144ffSStefano Zampini               break;
664a13144ffSStefano Zampini             }
665a13144ffSStefano Zampini           }
666a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
667a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
668a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
669a13144ffSStefano Zampini           } else {
670a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
671a13144ffSStefano Zampini           }
672a13144ffSStefano Zampini         }
673a13144ffSStefano Zampini       }
674a13144ffSStefano Zampini     }
675a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
676a13144ffSStefano Zampini   }
677a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
678a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
679c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
680a13144ffSStefano Zampini 
681a13144ffSStefano Zampini   /* Reset marked primal dofs */
682a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
683a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
684a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
685a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
686a13144ffSStefano Zampini 
6870569b399SStefano Zampini   /* Now use the initial lG */
6880569b399SStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
6890569b399SStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
6900569b399SStefano Zampini   lG   = lGinit;
6910569b399SStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
6920569b399SStefano Zampini 
693a13144ffSStefano Zampini   /* Compute extended cols indices */
694a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
695a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
696a13144ffSStefano Zampini   i   *= maxsize;
697a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extcols);CHKERRQ(ierr);
698a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&emarks);CHKERRQ(ierr);
699a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
700a13144ffSStefano Zampini   eerr = PETSC_FALSE;
701a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
702a13144ffSStefano Zampini     PetscInt size;
703a13144ffSStefano Zampini 
704a13144ffSStefano Zampini     cum  = 0;
705a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
706a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
707a13144ffSStefano Zampini     for (j=0;j<size;j++) {
708a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
709a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
710a13144ffSStefano Zampini     }
711a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
712a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
713a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
714a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
715a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
716a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
717a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
718a13144ffSStefano Zampini     if (cum != size -1) {
719a13144ffSStefano Zampini       emarks[i] = 1;
720a13144ffSStefano Zampini       if (print) {
721a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
722a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
723a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
724a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
725a13144ffSStefano Zampini       }
726a13144ffSStefano Zampini       eerr = PETSC_TRUE;
727a13144ffSStefano Zampini     }
728a13144ffSStefano Zampini   }
7294e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
730a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
731a13144ffSStefano Zampini   if (done) {
732a13144ffSStefano Zampini     PetscInt *newprimals;
733a13144ffSStefano Zampini 
734a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
735a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
736a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
737a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
738a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
7390569b399SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
740a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
741a13144ffSStefano Zampini       if (emarks[i]) {
742a13144ffSStefano Zampini         PetscInt size,mark = i+1;
743a13144ffSStefano Zampini 
744a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
745a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
746c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
747a13144ffSStefano Zampini         for (j=0;j<size;j++) {
748a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
749a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
750a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
751a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
752a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
753a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
754a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
755a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
756a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
757a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
758a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
759a13144ffSStefano Zampini                   /* finally set the new corners */
760a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
761a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
762a13144ffSStefano Zampini                   }
763a13144ffSStefano Zampini                 }
764a13144ffSStefano Zampini               }
765a13144ffSStefano Zampini             }
766a13144ffSStefano Zampini           }
767a13144ffSStefano Zampini         }
768a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
769a13144ffSStefano Zampini       }
770a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
771a13144ffSStefano Zampini     }
7720569b399SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
773a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
774c2151214SStefano Zampini     if (fl2g) {
775c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
776c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
777c2151214SStefano Zampini       for (i=0;i<nee;i++) {
778c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
779c2151214SStefano Zampini       }
780c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
781c2151214SStefano Zampini     }
782c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
783a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
784a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
785a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
786a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
787a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
788c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
789c2151214SStefano Zampini     if (fl2g) {
790c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
791c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
792c2151214SStefano Zampini       for (i=0;i<nee;i++) {
793c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
794c2151214SStefano Zampini       }
795c2151214SStefano Zampini     } else {
796c2151214SStefano Zampini       eedges  = alleedges;
797c2151214SStefano Zampini       primals = allprimals;
798c2151214SStefano Zampini     }
799a13144ffSStefano Zampini 
800a13144ffSStefano Zampini     /* Mark again */
801a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
802a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
803a13144ffSStefano Zampini       PetscInt size,mark = i+1;
804a13144ffSStefano Zampini 
805a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
806a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
807a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
808a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
809a13144ffSStefano Zampini     }
810a13144ffSStefano Zampini     if (print) {
811a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
812a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
813a13144ffSStefano Zampini     }
814a13144ffSStefano Zampini 
815a13144ffSStefano Zampini     /* Recompute extended cols */
816a13144ffSStefano Zampini     eerr = PETSC_FALSE;
817a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
818a13144ffSStefano Zampini       PetscInt size;
819a13144ffSStefano Zampini 
820a13144ffSStefano Zampini       cum  = 0;
821a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
822a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
823a13144ffSStefano Zampini       for (j=0;j<size;j++) {
824a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
825a13144ffSStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) {
826a13144ffSStefano Zampini           if (!PetscBTLookup(btv,jj[k])) {
827a13144ffSStefano Zampini             extrow[cum++] = jj[k];
828a13144ffSStefano Zampini           }
829a13144ffSStefano Zampini         }
830a13144ffSStefano Zampini       }
831a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
832a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
833a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
834a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
835a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
836a13144ffSStefano Zampini       if (cum != size -1) {
837a13144ffSStefano Zampini         if (print) {
838a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
839a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
840a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
841a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
842a13144ffSStefano Zampini         }
843a13144ffSStefano Zampini         eerr = PETSC_TRUE;
844a13144ffSStefano Zampini       }
845a13144ffSStefano Zampini     }
846a13144ffSStefano Zampini   }
847a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
848a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
849a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
850a13144ffSStefano Zampini   /* an error should not occur at this point */
851a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
852a13144ffSStefano Zampini 
8534e64d54eSstefano_zampini   /* Check the number of endpoints */
854c2151214SStefano Zampini   /* TODO: fix case for circular edge */
8554e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
8560569b399SStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8574e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
8584e64d54eSstefano_zampini     PetscInt size, found = 0;
8594e64d54eSstefano_zampini 
8604e64d54eSstefano_zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
8614e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8624e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
8634e64d54eSstefano_zampini     for (j=0;j<size;j++) {
8644e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
8654e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8664e64d54eSstefano_zampini         PetscInt vv = jj[k];
8674e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
8684e64d54eSstefano_zampini           found++;
8694e64d54eSstefano_zampini         }
8704e64d54eSstefano_zampini       }
8714e64d54eSstefano_zampini     }
8724e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
8734e64d54eSstefano_zampini     if (found != 2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d\n",found,i);
8744e64d54eSstefano_zampini   }
8750569b399SStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8764e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
8774e64d54eSstefano_zampini 
878a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
879a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
880a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
881a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
882a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
883a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
884a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
885a13144ffSStefano Zampini 
886a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
887a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
888a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
889a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
890a13144ffSStefano Zampini       if (emax < emarks[j]) {
891a13144ffSStefano Zampini         emax = emarks[j];
892a13144ffSStefano Zampini         eemax = j;
893a13144ffSStefano Zampini       }
894a13144ffSStefano Zampini     }
895a13144ffSStefano Zampini     /* not relevant for edges */
896a13144ffSStefano Zampini     if (!eemax) continue;
897a13144ffSStefano Zampini 
898a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
899a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
900c2151214SStefano 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]);
901a13144ffSStefano Zampini       }
902a13144ffSStefano Zampini     }
903a13144ffSStefano Zampini   }
904a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
905a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
906a13144ffSStefano Zampini #endif
907a13144ffSStefano Zampini 
908a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
909a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
910a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
911a13144ffSStefano Zampini   extmem *= maxsize;
912a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
913a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
914a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
915a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
916a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
917a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
918a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
919a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
920a13144ffSStefano Zampini         mark = marks[jj[j]];
921a13144ffSStefano Zampini 
922a13144ffSStefano Zampini     /* not relevant */
923a13144ffSStefano Zampini     if (!mark) continue;
924a13144ffSStefano Zampini 
925a13144ffSStefano Zampini     /* import extended row */
926a13144ffSStefano Zampini     mark--;
927a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
928a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
929a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
930a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
931a13144ffSStefano Zampini     extrowcum[mark] += size;
932a13144ffSStefano Zampini   }
933a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
934a13144ffSStefano Zampini   cum  = 0;
935a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
936a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
937a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
938a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
939a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
940a13144ffSStefano Zampini   }
941a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
942a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
943a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
945a13144ffSStefano Zampini 
946a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
947a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
948a13144ffSStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
949a13144ffSStefano Zampini   for (i=0;i<maxsize;i++) vals[i] = 1.;
950a13144ffSStefano Zampini 
951a13144ffSStefano Zampini   /* Create vectors for quadrature rules */
952c2151214SStefano Zampini   /* TODO preserve other quadratures */
953a13144ffSStefano Zampini   ierr = PetscMalloc1(nquads,&quads);CHKERRQ(ierr);
954a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
955a13144ffSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quads[i],NULL);CHKERRQ(ierr);
956a13144ffSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quads[i],el2g);CHKERRQ(ierr);
957a13144ffSStefano Zampini   }
958a13144ffSStefano Zampini   ierr = PCBDDCNullSpaceCreate(comm,PETSC_FALSE,nquads,quads,&nnsp);CHKERRQ(ierr);
959a13144ffSStefano Zampini 
960a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
961a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
962c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
963c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
964a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
965a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
966a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
967a13144ffSStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,el2g,el2g);CHKERRQ(ierr);
968a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
969a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
970a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
971a13144ffSStefano Zampini 
972a13144ffSStefano Zampini   /* Defaults to identity */
973c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
974a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
975a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
976a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
977a13144ffSStefano Zampini 
978a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
979a13144ffSStefano Zampini     Mat Gins = NULL, GKins = NULL;
980a13144ffSStefano Zampini 
981a13144ffSStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],&Gins,&GKins,work,rwork);CHKERRQ(ierr);
982a13144ffSStefano Zampini     if (Gins && GKins) {
983a13144ffSStefano Zampini       PetscScalar    *data;
984a13144ffSStefano Zampini       const PetscInt *rows,*cols;
985a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
986a13144ffSStefano Zampini 
987a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
988a13144ffSStefano Zampini       /* H1 */
989a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
990a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
991a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
992a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
993a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
994a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
995a13144ffSStefano Zampini       /* complement */
996a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
997a13144ffSStefano Zampini       if (ncc > nquads-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet supported ncc %d nquads %d",ncc,nquads);
998a13144ffSStefano 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);
999a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
1000a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
1001a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
1002a13144ffSStefano Zampini       /* Gins kernel quadratures */
1003a13144ffSStefano Zampini       for (j=0;j<ncc;j++) {
1004a13144ffSStefano Zampini         ierr = VecSetValueLocal(quads[j],cols[nch+j],1.,INSERT_VALUES);CHKERRQ(ierr);
1005a13144ffSStefano Zampini       }
1006a13144ffSStefano Zampini       /* H1 average */
1007a13144ffSStefano Zampini       ierr = VecSetValuesLocal(quads[nquads-1],nch,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1008a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1009a13144ffSStefano Zampini     }
1010a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1011a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1012a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1013a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1014a13144ffSStefano Zampini   }
1015a13144ffSStefano Zampini 
1016a13144ffSStefano Zampini   /* Start assembling */
1017a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1018a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1019a13144ffSStefano Zampini     ierr = VecAssemblyBegin(quads[i]);CHKERRQ(ierr);
1020a13144ffSStefano Zampini   }
1021a13144ffSStefano Zampini 
1022a13144ffSStefano Zampini   /* Free */
1023c2151214SStefano Zampini   if (fl2g) {
1024c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1025c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1026c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1027c2151214SStefano Zampini     }
1028c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1029c2151214SStefano Zampini   }
1030c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1031c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1032c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1033a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1034a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
1035c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1036c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1037a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1038a13144ffSStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1039a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1040a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1041a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1042a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1043a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1044a13144ffSStefano Zampini 
1045a13144ffSStefano Zampini   /* Complete assembling */
1046a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1047a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1048a13144ffSStefano Zampini     ierr = VecAssemblyEnd(quads[i]);CHKERRQ(ierr);
1049a13144ffSStefano Zampini   }
1050a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1051a13144ffSStefano Zampini     ierr = VecDestroy(&quads[i]);CHKERRQ(ierr);
1052a13144ffSStefano Zampini   }
1053a13144ffSStefano Zampini   ierr = PetscFree(quads);CHKERRQ(ierr);
1054a13144ffSStefano Zampini 
1055a13144ffSStefano Zampini   /* set change of basis */
1056a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
1057a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1058a13144ffSStefano Zampini 
1059a13144ffSStefano Zampini   /* set quadratures */
1060a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
1061a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
1062a13144ffSStefano Zampini 
1063a13144ffSStefano Zampini   PetscFunctionReturn(0);
1064a13144ffSStefano Zampini }
1065a13144ffSStefano Zampini 
1066d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1067d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1068d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1069d8203eabSStefano Zampini #undef __FUNCT__
1070d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1071d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1072d8203eabSStefano Zampini {
1073d8203eabSStefano Zampini   PetscErrorCode ierr;
1074d8203eabSStefano Zampini   PetscInt       i;
1075d8203eabSStefano Zampini 
1076d8203eabSStefano Zampini   PetscFunctionBegin;
1077d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1078d8203eabSStefano Zampini     PetscInt first,last;
1079d8203eabSStefano Zampini 
1080d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
108186fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1082d8203eabSStefano Zampini     if (i>=first && i < last) {
1083d8203eabSStefano Zampini       PetscScalar *data;
1084d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1085d8203eabSStefano Zampini       if (!has_const) {
1086d8203eabSStefano Zampini         data[i-first] = 1.;
1087d8203eabSStefano Zampini       } else {
108886fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
108986fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1090d8203eabSStefano Zampini       }
1091d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1092d8203eabSStefano Zampini     }
1093d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1094d8203eabSStefano Zampini   }
1095d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1096d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1097d8203eabSStefano Zampini     PetscInt first,last;
1098d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1099d8203eabSStefano Zampini     if (i>=first && i < last) {
1100d8203eabSStefano Zampini       PetscScalar *data;
1101d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1102d8203eabSStefano Zampini       if (!has_const) {
1103d8203eabSStefano Zampini         data[i-first] = 0.;
1104d8203eabSStefano Zampini       } else {
110586fa73c5SStefano Zampini         data[2*i-first] = 0.;
110686fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1107d8203eabSStefano Zampini       }
1108d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1109d8203eabSStefano Zampini     }
1110d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1111d8203eabSStefano Zampini   }
1112d8203eabSStefano Zampini   PetscFunctionReturn(0);
1113d8203eabSStefano Zampini }
1114d8203eabSStefano Zampini 
1115669cc0f4SStefano Zampini #undef __FUNCT__
1116669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
11178ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1118669cc0f4SStefano Zampini {
1119a198735bSStefano Zampini   Mat                    loc_divudotp;
1120fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
11218ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1122669cc0f4SStefano Zampini   IS                     *faces,*edges;
1123669cc0f4SStefano Zampini   PetscScalar            *vals;
1124669cc0f4SStefano Zampini   const PetscScalar      *array;
1125669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
11261ae86dd6SStefano Zampini   PetscMPIInt            rank;
1127a198735bSStefano Zampini   PetscErrorCode         ierr;
1128669cc0f4SStefano Zampini 
1129669cc0f4SStefano Zampini   PetscFunctionBegin;
1130669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1131669cc0f4SStefano Zampini   if (graph->twodim) {
1132669cc0f4SStefano Zampini     lmaxneighs = 2;
1133669cc0f4SStefano Zampini   } else {
1134669cc0f4SStefano Zampini     lmaxneighs = 1;
1135669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1136669cc0f4SStefano Zampini       const PetscInt *idxs;
1137669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1138669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1139669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1140669cc0f4SStefano Zampini     }
1141669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1142669cc0f4SStefano Zampini   }
1143669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1144669cc0f4SStefano Zampini   maxsize = 0;
1145669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1146669cc0f4SStefano Zampini     PetscInt nn;
1147669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1148669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1149669cc0f4SStefano Zampini   }
1150669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1151669cc0f4SStefano Zampini     PetscInt nn;
1152669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1153669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1154669cc0f4SStefano Zampini   }
1155669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1156669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1157669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
11588ae0ca82SStefano Zampini   if (!transpose) {
11598ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
11608ae0ca82SStefano Zampini   } else {
11618ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
11628ae0ca82SStefano Zampini   }
1163669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
11641ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1165d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1166669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
11678ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1168669cc0f4SStefano Zampini   }
1169d8203eabSStefano Zampini 
1170669cc0f4SStefano Zampini   /* compute local quad vec */
1171a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
11728ae0ca82SStefano Zampini   if (!transpose) {
1173a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
11748ae0ca82SStefano Zampini   } else {
11758ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
11768ae0ca82SStefano Zampini   }
1177669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
11788ae0ca82SStefano Zampini   if (!transpose) {
1179a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
11808ae0ca82SStefano Zampini   } else {
11818ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
11828ae0ca82SStefano Zampini   }
1183fa23a32eSStefano Zampini   if (vl2l) {
1184fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1185fa23a32eSStefano Zampini   } else {
1186fa23a32eSStefano Zampini     vins = v;
1187fa23a32eSStefano Zampini   }
1188fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1189669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
11909a962809SStefano Zampini 
11911ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
11921ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1193669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1194669cc0f4SStefano Zampini     const PetscInt    *idxs;
1195669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1196669cc0f4SStefano Zampini 
1197669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1198669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1199669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
12001ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1201669cc0f4SStefano Zampini     idx = -(idx+1);
1202669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1203669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1204669cc0f4SStefano Zampini   }
1205669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1206669cc0f4SStefano Zampini     const PetscInt    *idxs;
1207669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1208669cc0f4SStefano Zampini 
1209669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1210669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1211669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
12121ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1213669cc0f4SStefano Zampini     idx = -(idx+1);
1214669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1215669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1216669cc0f4SStefano Zampini   }
1217c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1218fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1219fa23a32eSStefano Zampini   if (vl2l) {
1220fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1221fa23a32eSStefano Zampini   }
1222669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1223669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1224669cc0f4SStefano Zampini 
1225669cc0f4SStefano Zampini   /* assemble near null space */
1226669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1227669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1228669cc0f4SStefano Zampini   }
1229669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1230669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1231669cc0f4SStefano Zampini   }
1232669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1233669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1234669cc0f4SStefano Zampini }
1235669cc0f4SStefano Zampini 
1236669cc0f4SStefano Zampini 
1237a3df083aSStefano Zampini #undef __FUNCT__
12381f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
12391f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
12401f4df5f7SStefano Zampini {
12411f4df5f7SStefano Zampini   PetscErrorCode ierr;
12421f4df5f7SStefano Zampini   Vec            local,global;
12431f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12441f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
12451f4df5f7SStefano Zampini 
12461f4df5f7SStefano Zampini   PetscFunctionBegin;
12471f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
12481f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
12491f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
12501f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
12511f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
12521f4df5f7SStefano Zampini       PetscInt i;
12531f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12541f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
12551f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12561f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12571f4df5f7SStefano Zampini       }
12581f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
12591f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
12601f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
12611f4df5f7SStefano Zampini     }
12621f4df5f7SStefano Zampini   } else {
1263986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
12641f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1265986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1266986cdee1SStefano Zampini       if (i > 1) {
1267986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
12681f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12691f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12701f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12711f4df5f7SStefano Zampini         }
12721f4df5f7SStefano Zampini       }
12731f4df5f7SStefano Zampini     }
1274986cdee1SStefano Zampini   }
12751f4df5f7SStefano Zampini 
12761f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
12771f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
12781f4df5f7SStefano Zampini   }
12791f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
12801f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
12811f4df5f7SStefano Zampini   }
12821f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
12831f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
12841f4df5f7SStefano Zampini   }
12851f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
12861f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
12871f4df5f7SStefano Zampini   PetscFunctionReturn(0);
12881f4df5f7SStefano Zampini }
12891f4df5f7SStefano Zampini 
12901f4df5f7SStefano Zampini #undef __FUNCT__
12913e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
12923e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
12933e589ea0SStefano Zampini {
12943e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
12953e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
12963e589ea0SStefano Zampini   PetscErrorCode    ierr;
12973e589ea0SStefano Zampini 
12983e589ea0SStefano Zampini   PetscFunctionBegin;
12993e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
13003e589ea0SStefano Zampini     PetscFunctionReturn(0);
13013e589ea0SStefano Zampini   }
13023e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
13033e589ea0SStefano Zampini     Vec swap;
13043e589ea0SStefano Zampini 
13053e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
13063e589ea0SStefano Zampini     swap = pcbddc->work_change;
13073e589ea0SStefano Zampini     pcbddc->work_change = r;
13083e589ea0SStefano Zampini     r = swap;
13093e589ea0SStefano Zampini   }
13103e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13113e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13123e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13133e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
13143e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13153e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13163e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
13173e589ea0SStefano Zampini     Vec swap;
13183e589ea0SStefano Zampini 
13193e589ea0SStefano Zampini     swap = r;
13203e589ea0SStefano Zampini     r = pcbddc->work_change;
13213e589ea0SStefano Zampini     pcbddc->work_change = swap;
13223e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
13233e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
13243e589ea0SStefano Zampini   }
13253e589ea0SStefano Zampini   PetscFunctionReturn(0);
13263e589ea0SStefano Zampini }
13273e589ea0SStefano Zampini 
13283e589ea0SStefano Zampini #undef __FUNCT__
1329a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1330a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1331a3df083aSStefano Zampini {
1332a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1333a3df083aSStefano Zampini   PetscErrorCode          ierr;
1334a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1335a3df083aSStefano Zampini 
1336a3df083aSStefano Zampini   PetscFunctionBegin;
1337a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1338a3df083aSStefano Zampini   if (transpose) {
1339a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1340a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1341a3df083aSStefano Zampini   } else {
1342a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1343a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1344a3df083aSStefano Zampini   }
1345a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1346a3df083aSStefano Zampini   if (apply_right) {
1347a3df083aSStefano Zampini     const PetscScalar *ax;
1348a3df083aSStefano Zampini     PetscInt          nl,i;
1349a3df083aSStefano Zampini 
1350a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1351a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1352a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1353a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1354a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1355a3df083aSStefano Zampini       PetscScalar    sum,val;
1356a3df083aSStefano Zampini       const PetscInt *idxs;
1357a3df083aSStefano Zampini       PetscInt       nz,j;
1358a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1359a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1360a3df083aSStefano Zampini       sum = 0.;
1361a3df083aSStefano Zampini       if (ctx->apply_p0) {
1362a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1363a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1364a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1365a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1366a3df083aSStefano Zampini         }
1367a3df083aSStefano Zampini       } else {
1368a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1369a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1370a3df083aSStefano Zampini         }
1371a3df083aSStefano Zampini       }
1372a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1373a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1374a3df083aSStefano Zampini     }
1375a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1376a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1377a3df083aSStefano Zampini   }
1378a3df083aSStefano Zampini   if (transpose) {
1379a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1380a3df083aSStefano Zampini   } else {
1381a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1382a3df083aSStefano Zampini   }
1383a3df083aSStefano Zampini   if (reset_x) {
1384a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1385a3df083aSStefano Zampini   }
1386a3df083aSStefano Zampini   if (apply_left) {
1387a3df083aSStefano Zampini     PetscScalar *ay;
1388a3df083aSStefano Zampini     PetscInt    i;
1389a3df083aSStefano Zampini 
1390a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1391a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1392a3df083aSStefano Zampini       PetscScalar    sum,val;
1393a3df083aSStefano Zampini       const PetscInt *idxs;
1394a3df083aSStefano Zampini       PetscInt       nz,j;
1395a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1396a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1397a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1398a3df083aSStefano Zampini       if (ctx->apply_p0) {
1399a3df083aSStefano Zampini         sum = 0.;
1400a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1401a3df083aSStefano Zampini           sum += ay[idxs[j]];
1402a3df083aSStefano Zampini           ay[idxs[j]] += val;
1403a3df083aSStefano Zampini         }
1404a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1405a3df083aSStefano Zampini       } else {
1406a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1407a3df083aSStefano Zampini           ay[idxs[j]] += val;
1408a3df083aSStefano Zampini         }
1409a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1410a3df083aSStefano Zampini       }
1411a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1412a3df083aSStefano Zampini     }
1413a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1414a3df083aSStefano Zampini   }
1415a3df083aSStefano Zampini   PetscFunctionReturn(0);
1416a3df083aSStefano Zampini }
1417a3df083aSStefano Zampini 
1418a3df083aSStefano Zampini #undef __FUNCT__
1419a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1420a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1421a3df083aSStefano Zampini {
1422a3df083aSStefano Zampini   PetscErrorCode ierr;
1423a3df083aSStefano Zampini 
1424a3df083aSStefano Zampini   PetscFunctionBegin;
1425a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1426a3df083aSStefano Zampini   PetscFunctionReturn(0);
1427a3df083aSStefano Zampini }
1428a3df083aSStefano Zampini 
1429a3df083aSStefano Zampini #undef __FUNCT__
1430a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1431a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1432a3df083aSStefano Zampini {
1433a3df083aSStefano Zampini   PetscErrorCode ierr;
1434a3df083aSStefano Zampini 
1435a3df083aSStefano Zampini   PetscFunctionBegin;
1436a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1437a3df083aSStefano Zampini   PetscFunctionReturn(0);
1438a3df083aSStefano Zampini }
1439a3df083aSStefano Zampini 
1440a3df083aSStefano Zampini #undef __FUNCT__
1441a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1442a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1443a3df083aSStefano Zampini {
1444a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1445a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1446a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1447a3df083aSStefano Zampini   PetscErrorCode          ierr;
1448a3df083aSStefano Zampini 
1449a3df083aSStefano Zampini   PetscFunctionBegin;
1450a3df083aSStefano Zampini   if (!restore) {
14511dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1452a3df083aSStefano Zampini     PetscScalar        *work;
1453b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1454a3df083aSStefano Zampini 
14559a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
14569a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1457a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1458a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1459a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1460a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1461a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1462a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1463a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1464a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1465a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1466a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1467a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1468a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1469059032f7SStefano Zampini     if (reuse) {
1470a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
14711dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1472059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1473059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1474059032f7SStefano Zampini       PetscInt               i;
1475059032f7SStefano Zampini 
1476059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1477059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1478059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1479059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1480059032f7SStefano Zampini       }
1481059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
14821dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1483059032f7SStefano Zampini     }
1484a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1485a3df083aSStefano Zampini     ctx->work = work;
1486a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1487a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1488a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1489a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1490a3df083aSStefano Zampini 
1491a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1492a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1493a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1494a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1495a3df083aSStefano Zampini   } else {
14961dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
14971dd7afcfSStefano Zampini       PetscFunctionReturn(0);
14981dd7afcfSStefano Zampini     }
1499a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1500a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1501a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
15021dd7afcfSStefano Zampini     ctx->A = NULL;
15031dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
15041dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
15051dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
15061dd7afcfSStefano Zampini     if (ctx->free) {
1507059032f7SStefano Zampini       PetscInt i;
15081dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1509059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1510059032f7SStefano Zampini       }
1511059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1512059032f7SStefano Zampini     }
1513a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1514a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1515a3df083aSStefano Zampini   }
1516a3df083aSStefano Zampini   PetscFunctionReturn(0);
1517a3df083aSStefano Zampini }
1518a3df083aSStefano Zampini 
1519a3df083aSStefano Zampini /* used just in bddc debug mode */
1520a3df083aSStefano Zampini #undef __FUNCT__
1521a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1522a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1523a3df083aSStefano Zampini {
1524a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1525a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1526a3df083aSStefano Zampini   Mat            An;
1527a3df083aSStefano Zampini   PetscErrorCode ierr;
1528a3df083aSStefano Zampini 
1529a3df083aSStefano Zampini   PetscFunctionBegin;
1530a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1531a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1532a3df083aSStefano Zampini   if (is1) {
1533a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1534a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1535a3df083aSStefano Zampini   } else {
1536a3df083aSStefano Zampini     *B = An;
1537a3df083aSStefano Zampini   }
1538a3df083aSStefano Zampini   PetscFunctionReturn(0);
1539a3df083aSStefano Zampini }
1540a3df083aSStefano Zampini 
15411cf9b237SStefano Zampini /* TODO: add reuse flag */
15421cf9b237SStefano Zampini #undef __FUNCT__
15431cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
15441cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
15451cf9b237SStefano Zampini {
15461cf9b237SStefano Zampini   Mat            Bt;
15471cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
15481cf9b237SStefano Zampini   const PetscInt *ii,*ij;
15491cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
15501cf9b237SStefano Zampini   PetscBool      flg_row;
15511cf9b237SStefano Zampini   PetscErrorCode ierr;
15521cf9b237SStefano Zampini 
15531cf9b237SStefano Zampini   PetscFunctionBegin;
15541cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
15551cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15561cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
15571cf9b237SStefano Zampini   nnz = n;
15581cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
15591cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
15601cf9b237SStefano Zampini   }
15611cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
15621cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
15631cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
15641cf9b237SStefano Zampini   nnz = 0;
15651cf9b237SStefano Zampini   bii[0] = 0;
15661cf9b237SStefano Zampini   for (i=0;i<n;i++) {
15671cf9b237SStefano Zampini     PetscInt j;
15681cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
15691cf9b237SStefano Zampini       PetscScalar entry = a[j];
15701cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
15711cf9b237SStefano Zampini         bij[nnz] = ij[j];
15721cf9b237SStefano Zampini         bdata[nnz] = entry;
15731cf9b237SStefano Zampini         nnz++;
15741cf9b237SStefano Zampini       }
15751cf9b237SStefano Zampini     }
15761cf9b237SStefano Zampini     bii[i+1] = nnz;
15771cf9b237SStefano Zampini   }
15781cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
15791cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
15801cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15811cf9b237SStefano Zampini   {
15821cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
15831cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
15841cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
15851cf9b237SStefano Zampini   }
15861cf9b237SStefano Zampini   *B = Bt;
15871cf9b237SStefano Zampini   PetscFunctionReturn(0);
15881cf9b237SStefano Zampini }
15891cf9b237SStefano Zampini 
1590674ae819SStefano Zampini #undef __FUNCT__
15914f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
15924f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
15934f1b2e48SStefano Zampini {
15944f1b2e48SStefano Zampini   Mat                    B;
15954f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
15964f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
15974f1b2e48SStefano Zampini   PCBDDCGraph            graph;
15984f1b2e48SStefano Zampini   PetscInt               i,n;
15994f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
16004f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
16014f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
16024f1b2e48SStefano Zampini   PetscErrorCode         ierr;
16034f1b2e48SStefano Zampini 
16044f1b2e48SStefano Zampini   PetscFunctionBegin;
160563c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
160663c961adSStefano Zampini     *ncc = 0;
160763c961adSStefano Zampini     *cc = NULL;
160863c961adSStefano Zampini     PetscFunctionReturn(0);
160963c961adSStefano Zampini   }
16104f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
16114f1b2e48SStefano Zampini   if (!isseqaij && filter) {
16121cf9b237SStefano Zampini     PetscBool isseqdense;
16131cf9b237SStefano Zampini 
16141cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
16151cf9b237SStefano Zampini     if (!isseqdense) {
16164f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
16171cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
16181cf9b237SStefano Zampini       PetscScalar *array;
16191cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
16201cf9b237SStefano Zampini 
16211cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
16221cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
16231cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
16241cf9b237SStefano Zampini       for (i=0;i<n;i++) {
16251cf9b237SStefano Zampini         PetscInt j;
16261cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
16271cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
16281cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
16291cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
16301cf9b237SStefano Zampini         }
16311cf9b237SStefano Zampini       }
16321cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
16339d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
16341cf9b237SStefano Zampini     }
16354f1b2e48SStefano Zampini   } else {
16364f1b2e48SStefano Zampini     B = A;
16374f1b2e48SStefano Zampini   }
16384f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16394f1b2e48SStefano Zampini 
16404f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
16414f1b2e48SStefano Zampini   if (filter) {
16424f1b2e48SStefano Zampini     PetscScalar *data;
16434f1b2e48SStefano Zampini     PetscInt    j,cum;
16444f1b2e48SStefano Zampini 
16454f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
16464f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
16474f1b2e48SStefano Zampini     cum = 0;
16484f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
16494f1b2e48SStefano Zampini       PetscInt t;
16504f1b2e48SStefano Zampini 
16514f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
16524f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
16534f1b2e48SStefano Zampini           continue;
16544f1b2e48SStefano Zampini         }
16554f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
16564f1b2e48SStefano Zampini       }
16574f1b2e48SStefano Zampini       t = xadj_filtered[i];
16584f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
16594f1b2e48SStefano Zampini       cum += t;
16604f1b2e48SStefano Zampini     }
16614f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
16624f1b2e48SStefano Zampini   } else {
16634f1b2e48SStefano Zampini     xadj_filtered = NULL;
16644f1b2e48SStefano Zampini     adjncy_filtered = NULL;
16654f1b2e48SStefano Zampini   }
16664f1b2e48SStefano Zampini 
16674f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
16684f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
16694f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
16704f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
16714f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1672be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
16734f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
16744f1b2e48SStefano Zampini   if (xadj_filtered) {
16754f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
16764f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
16774f1b2e48SStefano Zampini   } else {
16784f1b2e48SStefano Zampini     graph->xadj = xadj;
16794f1b2e48SStefano Zampini     graph->adjncy = adjncy;
16804f1b2e48SStefano Zampini   }
16814f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
16824f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
16834f1b2e48SStefano Zampini   /* partial clean up */
16844f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
16854f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16861cf9b237SStefano Zampini   if (A != B) {
16874f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
16884f1b2e48SStefano Zampini   }
16894f1b2e48SStefano Zampini 
16904f1b2e48SStefano Zampini   /* get back data */
16911cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
16921cf9b237SStefano Zampini   if (cc) {
16934f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
16944f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
16954f1b2e48SStefano 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);
16964f1b2e48SStefano Zampini     }
16974f1b2e48SStefano Zampini     *cc = cc_n;
16981cf9b237SStefano Zampini   }
16994f1b2e48SStefano Zampini   /* clean up graph */
17004f1b2e48SStefano Zampini   graph->xadj = 0;
17014f1b2e48SStefano Zampini   graph->adjncy = 0;
17024f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
17034f1b2e48SStefano Zampini   PetscFunctionReturn(0);
17044f1b2e48SStefano Zampini }
17054f1b2e48SStefano Zampini 
17064f1b2e48SStefano Zampini #undef __FUNCT__
17075408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
17085408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
17095408967cSStefano Zampini {
17105408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17115408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1712dee84bffSStefano Zampini   IS             dirIS = NULL;
17134f1b2e48SStefano Zampini   PetscInt       i;
17145408967cSStefano Zampini   PetscErrorCode ierr;
17155408967cSStefano Zampini 
17165408967cSStefano Zampini   PetscFunctionBegin;
1717dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
17185408967cSStefano Zampini   if (zerodiag) {
17195408967cSStefano Zampini     Mat            A;
17205408967cSStefano Zampini     Vec            vec3_N;
17215408967cSStefano Zampini     PetscScalar    *vals;
17225408967cSStefano Zampini     const PetscInt *idxs;
1723d12d3064SStefano Zampini     PetscInt       nz,*count;
17245408967cSStefano Zampini 
17255408967cSStefano Zampini     /* p0 */
17265408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
17275408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
17285408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17295408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17304f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
17315408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17325408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
17335408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
17345408967cSStefano Zampini     /* v_I */
17355408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
17365408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
17375408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17385408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
17395408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17405408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
17415408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17425408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17435408967cSStefano Zampini     if (dirIS) {
17445408967cSStefano Zampini       PetscInt n;
17455408967cSStefano Zampini 
17465408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
17475408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
17485408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
17495408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17505408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
17515408967cSStefano Zampini     }
17525408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
17535408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
17545408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
17555408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1756669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
17575408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
17585408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
17599a962809SStefano 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]));
17605408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
17615408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1762d12d3064SStefano Zampini 
1763d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1764d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1765d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1766d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1767d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1768d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17699a962809SStefano 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]);
1770d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1771d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
17725408967cSStefano Zampini   }
1773dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
17745408967cSStefano Zampini 
17755408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
17765408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
17774f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
17785408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
17794f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
17805408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1781f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1782f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1783f2a566d8SStefano 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);
1784f2a566d8SStefano Zampini   }
17855408967cSStefano Zampini   PetscFunctionReturn(0);
17865408967cSStefano Zampini }
17875408967cSStefano Zampini 
17885408967cSStefano Zampini #undef __FUNCT__
1789339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1790339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1791339f8db1SStefano Zampini {
1792339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17934f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1794b0f5fe93SStefano Zampini   PetscInt       nz,n;
17951f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
17964f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1797339f8db1SStefano Zampini   PetscErrorCode ierr;
1798339f8db1SStefano Zampini 
1799339f8db1SStefano Zampini   PetscFunctionBegin;
18009f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
18019f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1802a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1803a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1804a3df083aSStefano Zampini   }
1805a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1806a3df083aSStefano Zampini   pcbddc->benign_n = 0;
18071ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
18084f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
18094f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
18104f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
18111ae86dd6SStefano Zampini      since the local Schur complements are already SPD
18124f1b2e48SStefano Zampini   */
18134f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
18144f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
181540fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
18164f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
18174f1b2e48SStefano Zampini 
18184f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
18194f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
18204f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
18214f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1822ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
182340fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
182440fa8d13SStefano Zampini     if (!sorted) {
182540fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
182640fa8d13SStefano Zampini     }
182740fa8d13SStefano Zampini   } else {
182840fa8d13SStefano Zampini     pressures = NULL;
182940fa8d13SStefano Zampini   }
183097d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
183197d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
183227b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
183397d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1834339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1835339f8db1SStefano Zampini   if (!sorted) {
1836339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1837339f8db1SStefano Zampini   }
1838339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
18394f1b2e48SStefano Zampini   if (!nz) {
18404f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
18414f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
184240fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
184340fa8d13SStefano Zampini   }
18444f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
18454f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
18464f1b2e48SStefano Zampini   zerodiag_subs = NULL;
18474f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
18481f4df5f7SStefano Zampini   n_interior_dofs = 0;
18491f4df5f7SStefano Zampini   interior_dofs = NULL;
18501f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
18511f4df5f7SStefano Zampini     PetscInt n,i,j;
18521f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
18531f4df5f7SStefano Zampini     PetscInt *iwork;
18541f4df5f7SStefano Zampini 
18551f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
18561f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18571f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
18581f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
185990648384SStefano Zampini     for (i=1;i<n_neigh;i++)
18601f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
18611f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
18621f4df5f7SStefano Zampini     for (i=0;i<n;i++)
18631f4df5f7SStefano Zampini       if (!iwork[i])
18641f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
18651f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
18661f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18671f4df5f7SStefano Zampini   }
18684f1b2e48SStefano Zampini   if (has_null_pressures) {
18694f1b2e48SStefano Zampini     IS             *subs;
18701f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
18711f4df5f7SStefano Zampini     const PetscInt *idxs;
18721f4df5f7SStefano Zampini     PetscScalar    *array;
18731f4df5f7SStefano Zampini     Vec            *work;
18741f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
18754f1b2e48SStefano Zampini 
18764f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
18774f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
18781f4df5f7SStefano 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) */
18791f4df5f7SStefano Zampini     if (pcbddc->current_level) {
18801f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
18811f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
18821f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
18831f4df5f7SStefano Zampini       /* work[0] = 1_p */
18841f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
18851f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
18861f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
18871f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
18881f4df5f7SStefano Zampini       /* work[0] = 1_v */
18891f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
18901f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
18911f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
18921f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
18931f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
18941f4df5f7SStefano Zampini     }
18954f1b2e48SStefano Zampini     if (nsubs > 1) {
18964f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
18974f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
18984f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
18994f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
19004f1b2e48SStefano Zampini         PetscInt               nl;
19014f1b2e48SStefano Zampini 
19024f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
19034f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
19044f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
19054f1b2e48SStefano Zampini         if (nl) {
19064f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
19074f1b2e48SStefano Zampini 
19081f4df5f7SStefano Zampini           if (pcbddc->current_level) {
19091f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
19101f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
19111f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
19121f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19131f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
19141f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19151f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
19161f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
19171f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
19181f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
19191f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
19201f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
19211f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19221f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
19231f4df5f7SStefano Zampini                 break;
19241f4df5f7SStefano Zampini               }
19251f4df5f7SStefano Zampini             }
19261f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
19271f4df5f7SStefano Zampini           }
19281f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
19291f4df5f7SStefano Zampini             IS       t_bc;
19301f4df5f7SStefano Zampini             PetscInt nzb;
19311f4df5f7SStefano Zampini 
19321f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
19331f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
19341f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
19351f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
19361f4df5f7SStefano Zampini           }
19371f4df5f7SStefano Zampini           if (valid && pressures) {
19384f1b2e48SStefano Zampini             IS t_pressure_subs;
19394f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
19404f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
19414f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
19424f1b2e48SStefano Zampini           }
19434f1b2e48SStefano Zampini           if (valid) {
19444f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
19454f1b2e48SStefano Zampini             pcbddc->benign_n++;
19464f1b2e48SStefano Zampini           } else {
19474f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
19484f1b2e48SStefano Zampini           }
19494f1b2e48SStefano Zampini         }
19504f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
19514f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
19524f1b2e48SStefano Zampini       }
19534f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
19544f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
19551f4df5f7SStefano Zampini 
19561f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
19571f4df5f7SStefano Zampini         PetscInt nzb;
19581f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
19591f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
19601f4df5f7SStefano Zampini       }
19611f4df5f7SStefano Zampini       if (valid && pressures) {
19624f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
19634f1b2e48SStefano Zampini       }
19641f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
19651f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
19661f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
19671f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19681f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
19691f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19701f4df5f7SStefano Zampini               valid = PETSC_FALSE;
19711f4df5f7SStefano Zampini               break;
19721f4df5f7SStefano Zampini           }
19731f4df5f7SStefano Zampini         }
19741f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19751f4df5f7SStefano Zampini       }
19764f1b2e48SStefano Zampini       if (valid) {
19774f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1978ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
19794f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
19804f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
19814f1b2e48SStefano Zampini       }
19824f1b2e48SStefano Zampini     }
19831f4df5f7SStefano Zampini     if (pcbddc->current_level) {
19841f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
19854f1b2e48SStefano Zampini     }
19861f4df5f7SStefano Zampini   }
19871f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
19884f1b2e48SStefano Zampini 
19894f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1990b9b0e38cSStefano Zampini     PetscInt n;
1991b9b0e38cSStefano Zampini 
19924f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
19934f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1994b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1995b9b0e38cSStefano Zampini     if (n) {
19964f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
19974f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
19984f1b2e48SStefano Zampini     }
1999b9b0e38cSStefano Zampini   }
20004f1b2e48SStefano Zampini 
20014f1b2e48SStefano Zampini   /* final check for null pressures */
20024f1b2e48SStefano Zampini   if (zerodiag && pressures) {
20034f1b2e48SStefano Zampini     PetscInt nz,np;
20044f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
20054f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
20064f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
20074f1b2e48SStefano Zampini   }
20084f1b2e48SStefano Zampini 
20094f1b2e48SStefano Zampini   if (recompute_zerodiag) {
20104f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
20114f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
20124f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
20134f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
20144f1b2e48SStefano Zampini     } else {
20154f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
20164f1b2e48SStefano Zampini 
20174f1b2e48SStefano Zampini       nzn = 0;
20184f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20194f1b2e48SStefano Zampini         PetscInt ns;
20204f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20214f1b2e48SStefano Zampini         nzn += ns;
20224f1b2e48SStefano Zampini       }
20234f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
20244f1b2e48SStefano Zampini       nzn = 0;
20254f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20264f1b2e48SStefano Zampini         PetscInt ns,*idxs;
20274f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20284f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20294f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
20304f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20314f1b2e48SStefano Zampini         nzn += ns;
20324f1b2e48SStefano Zampini       }
20334f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
20344f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
20354f1b2e48SStefano Zampini     }
20364f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
20374f1b2e48SStefano Zampini   }
20384f1b2e48SStefano Zampini 
2039669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2040a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2041a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2042a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2043a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2044a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2045a198735bSStefano Zampini 
20461f4df5f7SStefano Zampini     if (pressures) {
20471f4df5f7SStefano Zampini       isused = pressures;
20481f4df5f7SStefano Zampini     } else {
20491f4df5f7SStefano Zampini       isused = zerodiag;
20501f4df5f7SStefano Zampini     }
2051a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2052669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
20531ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
20541ae86dd6SStefano 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");
2055a198735bSStefano Zampini     n_isused = 0;
2056a198735bSStefano Zampini     if (isused) {
2057a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2058a198735bSStefano Zampini     }
2059a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2060a198735bSStefano Zampini     st = st-n_isused;
20611ae86dd6SStefano Zampini     if (n) {
2062a198735bSStefano Zampini       const PetscInt *gidxs;
2063a198735bSStefano Zampini 
2064a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2065a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2066a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2067a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2068a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2069a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
20701ae86dd6SStefano Zampini     } else {
2071a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2072a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2073a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2074a198735bSStefano Zampini     }
2075a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2076a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2077a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2078a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2079a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2080a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2081a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2082a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2083a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2084a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2085a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2086a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2087a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2088a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
20891ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20901ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20911ae86dd6SStefano Zampini   }
2092b3afcdbeSStefano Zampini 
2093b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
20944f1b2e48SStefano Zampini   if (has_null_pressures) {
20954f1b2e48SStefano Zampini     IS             zerodiagc;
20964f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
20974f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
20984f1b2e48SStefano Zampini 
20994f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2100339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2101339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2102339f8db1SStefano Zampini     /* local change of basis for pressures */
2103339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
210497d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2105339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2106339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2107339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
21084f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
21094f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
21104f1b2e48SStefano Zampini       PetscInt nzs,j;
21114f1b2e48SStefano Zampini 
21124f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
21134f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21144f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
21154f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
21164f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21174f1b2e48SStefano Zampini     }
2118339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2119339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2120339f8db1SStefano Zampini     /* set identity on velocities */
2121339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2122339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2123339f8db1SStefano Zampini     }
21244f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
21254f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
21269f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
21274f1b2e48SStefano 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);
2128339f8db1SStefano Zampini     /* set change on pressures */
21294f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
21304f1b2e48SStefano Zampini       PetscScalar *array;
21314f1b2e48SStefano Zampini       PetscInt    nzs;
21324f1b2e48SStefano Zampini 
21334f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
21344f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
21354f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2136339f8db1SStefano Zampini         PetscScalar vals[2];
2137339f8db1SStefano Zampini         PetscInt    cols[2];
2138339f8db1SStefano Zampini 
2139339f8db1SStefano Zampini         cols[0] = idxs[i];
21404f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2141339f8db1SStefano Zampini         vals[0] = 1.;
2142b0f5fe93SStefano Zampini         vals[1] = 1.;
21434f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2144339f8db1SStefano Zampini       }
21454f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
21464f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
21474f1b2e48SStefano Zampini       array[nzs-1] = 1.;
21484f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
21494f1b2e48SStefano Zampini       /* store local idxs for p0 */
21504f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
21514f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2152339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
21534f1b2e48SStefano Zampini     }
2154339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2155339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2156a3df083aSStefano Zampini     /* project if needed */
2157a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
21581dd7afcfSStefano Zampini       Mat M;
21591dd7afcfSStefano Zampini 
21601dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2161339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
21621dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
21631dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2164a3df083aSStefano Zampini     }
21654f1b2e48SStefano Zampini     /* store global idxs for p0 */
21664f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2167339f8db1SStefano Zampini   }
2168ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
21694f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2170b0f5fe93SStefano Zampini 
2171b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2172b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
217327b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
217427b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2175339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2176339f8db1SStefano Zampini   PetscFunctionReturn(0);
2177339f8db1SStefano Zampini }
2178339f8db1SStefano Zampini 
2179339f8db1SStefano Zampini #undef __FUNCT__
2180015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2181015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2182efc2fbd9SStefano Zampini {
2183efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2184de9d7bd0SStefano Zampini   PetscScalar    *array;
2185efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2186efc2fbd9SStefano Zampini 
2187efc2fbd9SStefano Zampini   PetscFunctionBegin;
2188efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2189efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
21904f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2191efc2fbd9SStefano Zampini   }
2192de9d7bd0SStefano Zampini   if (get) {
2193efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
21944f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
21954f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2196efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2197de9d7bd0SStefano Zampini   } else {
2198de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2199de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2200de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2201de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2202efc2fbd9SStefano Zampini   }
2203efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2204efc2fbd9SStefano Zampini }
2205efc2fbd9SStefano Zampini 
2206efc2fbd9SStefano Zampini #undef __FUNCT__
2207c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2208c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2209c263805aSStefano Zampini {
2210c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2211c263805aSStefano Zampini   PetscErrorCode ierr;
2212c263805aSStefano Zampini 
2213c263805aSStefano Zampini   PetscFunctionBegin;
2214c263805aSStefano Zampini   /* TODO: add error checking
2215c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2216c263805aSStefano Zampini     - cannot push before pop.
22171c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2218c263805aSStefano Zampini   */
22194f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2220efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2221efc2fbd9SStefano Zampini   }
2222c263805aSStefano Zampini   if (pop) {
2223a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22244f1b2e48SStefano Zampini       IS       is_p0;
22254f1b2e48SStefano Zampini       MatReuse reuse;
2226c263805aSStefano Zampini 
2227c263805aSStefano Zampini       /* extract B_0 */
22284f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
22294f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
22304f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
22314f1b2e48SStefano Zampini       }
22324f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
22334f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2234c263805aSStefano Zampini       /* remove rows and cols from local problem */
2235c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
223697d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
22374f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
22384f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2239a3df083aSStefano Zampini     } else {
2240a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2241a3df083aSStefano Zampini       PetscScalar *vals;
2242a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2243a3df083aSStefano Zampini 
2244a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2245a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2246a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
22470b5adadeSStefano Zampini         PetscInt *nnz;
2248a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2249a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2250a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2251331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2252331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2253331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2254331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2255331e053bSStefano Zampini         }
2256331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2257331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2258331e053bSStefano Zampini       }
2259a3df083aSStefano Zampini 
2260a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2261a3df083aSStefano Zampini         PetscScalar *array;
2262a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2263a3df083aSStefano Zampini 
2264a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2265a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2266a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2267a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2268a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2269a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2270a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2271a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2272a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2273a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2274a3df083aSStefano Zampini         cum = 0;
2275a3df083aSStefano Zampini         for (j=0;j<n;j++) {
227622db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2277a3df083aSStefano Zampini             vals[cum] = array[j];
2278a3df083aSStefano Zampini             idxs_ins[cum] = j;
2279a3df083aSStefano Zampini             cum++;
2280a3df083aSStefano Zampini           }
2281a3df083aSStefano Zampini         }
2282a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2283a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2284a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2285a3df083aSStefano Zampini       }
2286a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2287a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2288a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2289a3df083aSStefano Zampini     }
2290c263805aSStefano Zampini   } else { /* push */
2291a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22924f1b2e48SStefano Zampini       PetscInt i;
22934f1b2e48SStefano Zampini 
22944f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
22954f1b2e48SStefano Zampini         PetscScalar *B0_vals;
22964f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
22974f1b2e48SStefano Zampini 
22984f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22994f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
23007b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
23014f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
23024f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
23034f1b2e48SStefano Zampini       }
2304c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2305c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2306a3df083aSStefano Zampini     } else {
2307a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2308a3df083aSStefano Zampini     }
2309c263805aSStefano Zampini   }
2310c263805aSStefano Zampini   PetscFunctionReturn(0);
2311c263805aSStefano Zampini }
2312c263805aSStefano Zampini 
2313c263805aSStefano Zampini #undef __FUNCT__
2314b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
231508122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2316b1b3d7a2SStefano Zampini {
2317b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
231808122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
231908122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
232008122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
232108122e43SStefano Zampini   PetscScalar     *work,lwork;
232208122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
232308122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
232408122e43SStefano Zampini   PetscReal       *eigs,thresh;
23251b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2326f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
232708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
232808122e43SStefano Zampini   PetscReal       *rwork;
232908122e43SStefano Zampini #endif
2330b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2331b1b3d7a2SStefano Zampini 
2332b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2333b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2334af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2335af25d912SStefano 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);
233606a4e24aSStefano Zampini 
2337fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2338fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2339fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2340fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
23411575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2342fd14bc51SStefano Zampini   }
2343fd14bc51SStefano Zampini 
2344e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2345e496cd5dSStefano 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);
2346e496cd5dSStefano Zampini   }
2347e496cd5dSStefano Zampini 
234808122e43SStefano Zampini   /* max size of subsets */
234908122e43SStefano Zampini   mss = 0;
235008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
235108122e43SStefano Zampini     PetscInt subset_size;
2352862806e4SStefano Zampini 
235308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
235408122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
235508122e43SStefano Zampini   }
235608122e43SStefano Zampini 
235708122e43SStefano Zampini   /* min/max and threshold */
235808122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2359f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
236008122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2361f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2362f6f667cfSStefano Zampini   if (nmin) {
2363f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2364f6f667cfSStefano Zampini   }
236508122e43SStefano Zampini 
236608122e43SStefano Zampini   /* allocate lapack workspace */
236708122e43SStefano Zampini   cum = cum2 = 0;
236808122e43SStefano Zampini   maxneigs = 0;
236908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
237008122e43SStefano Zampini     PetscInt n,subset_size;
2371f6f667cfSStefano Zampini 
237208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
237308122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
23749162d606SStefano Zampini     cum += subset_size;
23759162d606SStefano Zampini     cum2 += subset_size*n;
237608122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
237708122e43SStefano Zampini   }
237808122e43SStefano Zampini   if (mss) {
23799ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
238008122e43SStefano Zampini       PetscBLASInt B_itype = 1;
238108122e43SStefano Zampini       PetscBLASInt B_N = mss;
23824c6709b3SStefano Zampini       PetscReal    zero = 0.0;
23834c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
238408122e43SStefano Zampini 
238508122e43SStefano Zampini       B_lwork = -1;
238608122e43SStefano Zampini       S = NULL;
238708122e43SStefano Zampini       St = NULL;
2388a58a30b4SStefano Zampini       eigs = NULL;
2389a58a30b4SStefano Zampini       eigv = NULL;
2390a58a30b4SStefano Zampini       B_iwork = NULL;
2391a58a30b4SStefano Zampini       B_ifail = NULL;
2392d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2393d1710679SStefano Zampini       rwork = NULL;
2394d1710679SStefano Zampini #endif
23958bec7fa6SStefano Zampini       thresh = 1.0;
239608122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
239708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
239808122e43SStefano 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));
239908122e43SStefano Zampini #else
240008122e43SStefano 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));
240108122e43SStefano Zampini #endif
240208122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
240308122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
240408122e43SStefano Zampini     } else {
240508122e43SStefano Zampini         /* TODO */
240608122e43SStefano Zampini     }
240708122e43SStefano Zampini   } else {
240808122e43SStefano Zampini     lwork = 0;
240908122e43SStefano Zampini   }
241008122e43SStefano Zampini 
241108122e43SStefano Zampini   nv = 0;
2412d62866d3SStefano 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) */
2413d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
241408122e43SStefano Zampini   }
24154c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2416f6f667cfSStefano Zampini   if (allocated_S_St) {
2417f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2418f6f667cfSStefano Zampini   }
2419f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
242008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
242108122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
242208122e43SStefano Zampini #endif
24239162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
24249162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
24259162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
242608122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
24279162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
242808122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
242908122e43SStefano Zampini 
243008122e43SStefano Zampini   maxneigs = 0;
243172b8c272SStefano Zampini   cum = cumarray = 0;
24329162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
24339162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2434d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
243508122e43SStefano Zampini     const PetscInt *idxs;
243608122e43SStefano Zampini 
2437d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
243808122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
243908122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
244008122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
244108122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
24429162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
24439162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
244408122e43SStefano Zampini     }
2445d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
244608122e43SStefano Zampini   }
244708122e43SStefano Zampini 
244808122e43SStefano Zampini   if (mss) { /* multilevel */
244908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
245008122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
245108122e43SStefano Zampini   }
245208122e43SStefano Zampini 
2453ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
245408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
245508122e43SStefano Zampini     const PetscInt *idxs;
24569d54b7f4SStefano Zampini     PetscReal      upper,lower;
2457862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
245808122e43SStefano Zampini     PetscBLASInt   B_N;
2459aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
246008122e43SStefano Zampini 
24619d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
24629d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
24639d54b7f4SStefano Zampini       lower = thresh;
24649d54b7f4SStefano Zampini     } else {
24659d54b7f4SStefano Zampini       upper = 1./thresh;
24669d54b7f4SStefano Zampini       lower = 0.;
24679d54b7f4SStefano Zampini     }
2468862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2469ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2470f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2471f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
24729ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2473aff50787SStefano Zampini         PetscInt j,k;
2474aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2475aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2476aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
247708122e43SStefano Zampini         }
247808122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2479aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2480aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2481aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2482aff50787SStefano Zampini           }
248308122e43SStefano Zampini         }
248408122e43SStefano Zampini       } else {
248508122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248608122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248708122e43SStefano Zampini       }
24888bec7fa6SStefano Zampini     } else {
2489f6f667cfSStefano Zampini       S = Sarray + cumarray;
2490f6f667cfSStefano Zampini       St = Starray + cumarray;
24918bec7fa6SStefano Zampini     }
2492aff50787SStefano Zampini     /* see if we can save some work */
2493b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2494aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2495aff50787SStefano Zampini     }
2496aff50787SStefano Zampini 
2497b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2498aff50787SStefano Zampini       B_neigs = 0;
2499aff50787SStefano Zampini     } else {
25009ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
250108122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2502f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
25034c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
25049552c7c7SStefano Zampini         PetscInt     nmin_s;
2505b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
250608122e43SStefano Zampini 
2507fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
25088bec7fa6SStefano Zampini           PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %d/%d %d %d.\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]);
2509fd14bc51SStefano Zampini         }
2510d16cbb6bSStefano Zampini 
2511b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2512b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2513b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2514b7ab4a40SStefano Zampini         }
2515b7ab4a40SStefano Zampini 
251608122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2517b7ab4a40SStefano Zampini         if (compute_range) {
2518d16cbb6bSStefano Zampini 
2519d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
252008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25219d54b7f4SStefano 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));
252208122e43SStefano Zampini #else
25239d54b7f4SStefano 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));
252408122e43SStefano Zampini #endif
2525b7ab4a40SStefano Zampini         } else if (!same_data) {
2526d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2527d16cbb6bSStefano Zampini           B_IL = 1;
2528d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
25299d54b7f4SStefano 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));
2530d16cbb6bSStefano Zampini #else
25319d54b7f4SStefano 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));
2532d16cbb6bSStefano Zampini #endif
2533b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2534b7ab4a40SStefano Zampini           PetscInt k;
2535b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2536b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2537b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2538b7ab4a40SStefano Zampini           nmin = nmax;
2539b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2540b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2541b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2542b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2543b7ab4a40SStefano Zampini           }
2544d16cbb6bSStefano Zampini         }
254508122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
254608122e43SStefano Zampini         if (B_ierr) {
25476c4ed002SBarry 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);
25486c4ed002SBarry 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);
25496c4ed002SBarry 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);
255008122e43SStefano Zampini         }
255108122e43SStefano Zampini 
255208122e43SStefano Zampini         if (B_neigs > nmax) {
2553fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2554fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2555fd14bc51SStefano Zampini           }
25569d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
255708122e43SStefano Zampini           B_neigs = nmax;
255808122e43SStefano Zampini         }
255908122e43SStefano Zampini 
25609552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
25619552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
256208122e43SStefano Zampini           PetscBLASInt B_neigs2;
256308122e43SStefano Zampini 
25649d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2565f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
25669d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
25679d54b7f4SStefano Zampini           } else {
25689d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
25699d54b7f4SStefano Zampini             B_IU = nmin_s;
25709d54b7f4SStefano Zampini           }
2571fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2572fd14bc51SStefano 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);
2573fd14bc51SStefano Zampini           }
25749ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
25751ae86dd6SStefano Zampini             PetscInt j,k;
257608122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
25771ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
25781ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
25791ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
258008122e43SStefano Zampini               }
258108122e43SStefano Zampini             }
258208122e43SStefano Zampini           } else {
258308122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258408122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258508122e43SStefano Zampini           }
258608122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
258708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25889d54b7f4SStefano 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));
258908122e43SStefano Zampini #else
25909d54b7f4SStefano 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));
259108122e43SStefano Zampini #endif
259208122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
259308122e43SStefano Zampini           B_neigs += B_neigs2;
259408122e43SStefano Zampini         }
259508122e43SStefano Zampini         if (B_ierr) {
25966c4ed002SBarry 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);
25976c4ed002SBarry 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);
25986c4ed002SBarry 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);
259908122e43SStefano Zampini         }
2600fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2601ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
260208122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
260308122e43SStefano Zampini             if (eigs[j] == 0.0) {
2604ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
260508122e43SStefano Zampini             } else {
26069d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2607ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
26089d54b7f4SStefano Zampini               } else {
26099d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
26109d54b7f4SStefano Zampini               }
2611fd14bc51SStefano Zampini             }
261208122e43SStefano Zampini           }
261308122e43SStefano Zampini         }
261408122e43SStefano Zampini       } else {
261508122e43SStefano Zampini           /* TODO */
261608122e43SStefano Zampini       }
2617aff50787SStefano Zampini     }
26186c3e6151SStefano Zampini     /* change the basis back to the original one */
26196c3e6151SStefano Zampini     if (sub_schurs->change) {
262072b8c272SStefano Zampini       Mat change,phi,phit;
26216c3e6151SStefano Zampini 
26226c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26236c3e6151SStefano Zampini         PetscInt ii;
26246c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
26256c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26266c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2627684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2628684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2629684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2630684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2631684229deSStefano Zampini #else
26326c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2633684229deSStefano Zampini #endif
26346c3e6151SStefano Zampini           }
26356c3e6151SStefano Zampini         }
26366c3e6151SStefano Zampini       }
263772b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
26386c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
263972b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
26406c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
26416c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
26426c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
26436c3e6151SStefano Zampini     }
26448bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
26458bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
26469162d606SStefano Zampini     if (B_neigs) {
26479162d606SStefano 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);
2648fd14bc51SStefano Zampini 
2649fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26509552c7c7SStefano Zampini         PetscInt ii;
26519552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2652ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26539552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2654ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2655ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2656ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2657ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2658ac47001eSStefano Zampini #else
2659ac47001eSStefano 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);
2660ac47001eSStefano Zampini #endif
26619552c7c7SStefano Zampini           }
26629552c7c7SStefano Zampini         }
2663fd14bc51SStefano Zampini       }
26649162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
26659162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
26669162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
26679162d606SStefano Zampini       cum++;
266808122e43SStefano Zampini     }
266908122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
267008122e43SStefano Zampini     /* shift for next computation */
267108122e43SStefano Zampini     cumarray += subset_size*subset_size;
267208122e43SStefano Zampini   }
2673fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2674fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2675fd14bc51SStefano Zampini   }
267608122e43SStefano Zampini 
267708122e43SStefano Zampini   if (mss) {
267808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
267908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2680f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2681f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2682f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
268308122e43SStefano Zampini   }
2684f6f667cfSStefano Zampini   if (allocated_S_St) {
2685f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2686f6f667cfSStefano Zampini   }
2687f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
268808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
268908122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
269008122e43SStefano Zampini #endif
269108122e43SStefano Zampini   if (pcbddc->dbg_flag) {
26921b968477SStefano Zampini     PetscInt maxneigs_r;
2693b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
26949b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
269508122e43SStefano Zampini   }
269608122e43SStefano Zampini   PetscFunctionReturn(0);
269708122e43SStefano Zampini }
2698b1b3d7a2SStefano Zampini 
2699674ae819SStefano Zampini #undef __FUNCT__
2700c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2701c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2702c8587f34SStefano Zampini {
27038629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2704c8587f34SStefano Zampini   PetscErrorCode ierr;
2705c8587f34SStefano Zampini 
2706c8587f34SStefano Zampini   PetscFunctionBegin;
2707f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
27085e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2709c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2710c8587f34SStefano Zampini 
2711684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
27120fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2713684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2714c8587f34SStefano Zampini 
27158629588bSStefano Zampini   /*
27168629588bSStefano Zampini      Setup local correction and local part of coarse basis.
27178629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
27188629588bSStefano Zampini   */
271947f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
27208629588bSStefano Zampini 
27218629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
27228629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
27238629588bSStefano Zampini 
27248629588bSStefano Zampini   /* free */
27258629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2726c8587f34SStefano Zampini   PetscFunctionReturn(0);
2727c8587f34SStefano Zampini }
2728c8587f34SStefano Zampini 
2729c8587f34SStefano Zampini #undef __FUNCT__
2730674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2731674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2732674ae819SStefano Zampini {
2733674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2734674ae819SStefano Zampini   PetscErrorCode ierr;
2735674ae819SStefano Zampini 
2736674ae819SStefano Zampini   PetscFunctionBegin;
2737674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
273830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2739674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2740785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2741674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2742f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2743f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2744785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
274563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
274663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2747674ae819SStefano Zampini   PetscFunctionReturn(0);
2748674ae819SStefano Zampini }
2749674ae819SStefano Zampini 
2750674ae819SStefano Zampini #undef __FUNCT__
2751674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2752674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2753674ae819SStefano Zampini {
2754674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
27554f1b2e48SStefano Zampini   PetscInt       i;
2756674ae819SStefano Zampini   PetscErrorCode ierr;
2757674ae819SStefano Zampini 
2758674ae819SStefano Zampini   PetscFunctionBegin;
2759a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2760b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2761674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
276216909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
27631dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2764674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2765669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2766fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2767a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2768674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
27694f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
27704f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
27714f1b2e48SStefano Zampini   }
27724f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2773b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2774b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2775b334f244SStefano Zampini   }
2776c703fcc7SStefano Zampini   pcbddc->graphanalyzed        = PETSC_FALSE;
2777*8af8fcf9SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
2778674ae819SStefano Zampini   PetscFunctionReturn(0);
2779674ae819SStefano Zampini }
2780674ae819SStefano Zampini 
2781674ae819SStefano Zampini #undef __FUNCT__
2782674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2783674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2784674ae819SStefano Zampini {
2785674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2786674ae819SStefano Zampini   PetscErrorCode ierr;
2787674ae819SStefano Zampini 
2788674ae819SStefano Zampini   PetscFunctionBegin;
2789674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
279058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2791ca92afb2SStefano Zampini     PetscScalar *array;
279206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
279306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
279458da7f69SStefano Zampini   }
2795674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2796674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
279715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
279815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2799674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2800674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2801674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
280206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2803674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2804674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28058ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2806674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2807674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2808674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2809f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2810f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2811f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2812f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2813727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
28140e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2815f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
281670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
281781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
28180369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
28191dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
28204f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
28218b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2822ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2823ca92afb2SStefano Zampini     PetscInt i;
2824ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2825ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2826ca92afb2SStefano Zampini     }
2827ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2828ca92afb2SStefano Zampini   }
28294f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2830674ae819SStefano Zampini   PetscFunctionReturn(0);
2831674ae819SStefano Zampini }
2832674ae819SStefano Zampini 
2833674ae819SStefano Zampini #undef __FUNCT__
2834f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2835f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
28366bfb1811SStefano Zampini {
28376bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
28386bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
28396bfb1811SStefano Zampini   VecType        impVecType;
28404f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
28416bfb1811SStefano Zampini   PetscErrorCode ierr;
28426bfb1811SStefano Zampini 
28436bfb1811SStefano Zampini   PetscFunctionBegin;
28446c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2845e7b262bdSStefano Zampini   /* get sizes */
28464f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2847b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
28486bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2849e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2850e7b262bdSStefano Zampini   /* R nodes */
2851e7b262bdSStefano Zampini   old_size = -1;
2852e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2853e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2854e7b262bdSStefano Zampini   }
2855e7b262bdSStefano Zampini   if (n_R != old_size) {
2856e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2857e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28586bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
28596bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
28606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
28616bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2862e7b262bdSStefano Zampini   }
2863e7b262bdSStefano Zampini   /* local primal dofs */
2864e7b262bdSStefano Zampini   old_size = -1;
2865e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2866e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2867e7b262bdSStefano Zampini   }
2868e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2869e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
287083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2871e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
28726bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2873e7b262bdSStefano Zampini   }
2874e7b262bdSStefano Zampini   /* local explicit constraints */
2875e7b262bdSStefano Zampini   old_size = -1;
2876e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2877e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2878e7b262bdSStefano Zampini   }
2879e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2880e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
288183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
288283b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
288383b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
288483b7ccabSStefano Zampini   }
28856bfb1811SStefano Zampini   PetscFunctionReturn(0);
28866bfb1811SStefano Zampini }
28876bfb1811SStefano Zampini 
28886bfb1811SStefano Zampini #undef __FUNCT__
288947f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
289047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
289188ebb749SStefano Zampini {
289225084f0cSStefano Zampini   PetscErrorCode  ierr;
289325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
289488ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
289588ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2896d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
289725084f0cSStefano Zampini   /* submatrices of local problem */
289880677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
289906656605SStefano Zampini   /* submatrices of local coarse problem */
290006656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
290125084f0cSStefano Zampini   /* working matrices */
290206656605SStefano Zampini   Mat             C_CR;
290325084f0cSStefano Zampini   /* additional working stuff */
290406656605SStefano Zampini   PC              pc_R;
29054f1b2e48SStefano Zampini   Mat             F;
29065cbda25cSStefano Zampini   Vec             dummy_vec;
2907a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
290825084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
290906656605SStefano Zampini   PetscScalar     *work;
291006656605SStefano Zampini   PetscInt        *idx_V_B;
2911ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
291206656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2913ffd830a3SStefano Zampini 
291425084f0cSStefano Zampini   /* some shortcuts to scalars */
291506656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
291688ebb749SStefano Zampini 
291788ebb749SStefano Zampini   PetscFunctionBegin;
29189a962809SStefano 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");
2919ffd830a3SStefano Zampini 
2920ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2921b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29224f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2923b371cd4fSStefano Zampini   n_B = pcis->n_B;
2924b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
292588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
292688ebb749SStefano Zampini 
292788ebb749SStefano Zampini   /* vertices in boundary numbering */
2928785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
29290e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
29306c4ed002SBarry 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);
293188ebb749SStefano Zampini 
293206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2933019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
293406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
293506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
293606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
293706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
293806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
293906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
294006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
294106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
294206656605SStefano Zampini 
294306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
294406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
294506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
294606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
294706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2948ffd830a3SStefano Zampini   lda_rhs = n_R;
2949a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
295006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
295106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2952b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2953df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2954d62866d3SStefano Zampini     MatFactorType      type;
2955d62866d3SStefano Zampini 
2956df4d28bfSStefano Zampini     F = reuse_solver->F;
29576816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2958d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2959ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
296022db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
296106656605SStefano Zampini   } else {
296206656605SStefano Zampini     F = NULL;
296306656605SStefano Zampini   }
296406656605SStefano Zampini 
2965ffd830a3SStefano Zampini   /* allocate workspace */
2966ffd830a3SStefano Zampini   n = 0;
2967ffd830a3SStefano Zampini   if (n_constraints) {
2968ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2969ffd830a3SStefano Zampini   }
2970ffd830a3SStefano Zampini   if (n_vertices) {
2971ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2972ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2973ffd830a3SStefano Zampini   }
2974ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2975ffd830a3SStefano Zampini 
29765cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
29775cbda25cSStefano Zampini   dummy_vec = NULL;
29785cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
29795cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
29805cbda25cSStefano Zampini   }
29815cbda25cSStefano Zampini 
298288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
298388ebb749SStefano Zampini   if (n_constraints) {
298472b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
298506656605SStefano Zampini     IS          is_aux;
298680677318SStefano Zampini     PetscScalar *array,*array2;
298706656605SStefano Zampini 
2988f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
298980677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
299088ebb749SStefano Zampini 
299125084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
299225084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
29938ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
299472b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
299588ebb749SStefano Zampini 
299680677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
299780677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2998ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
299988ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
300006656605SStefano Zampini       const PetscScalar *row_cmat_values;
300106656605SStefano Zampini       const PetscInt    *row_cmat_indices;
300206656605SStefano Zampini       PetscInt          size_of_constraint,j;
300388ebb749SStefano Zampini 
300406656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300506656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
3006ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
300706656605SStefano Zampini       }
300806656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300906656605SStefano Zampini     }
3010ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
301106656605SStefano Zampini     if (F) {
301206656605SStefano Zampini       Mat B;
301306656605SStefano Zampini 
3014ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
3015a3df083aSStefano Zampini       if (need_benign_correction) {
3016df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3017a3df083aSStefano Zampini 
301872b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
301972b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3020a3df083aSStefano Zampini       }
302180677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
3022a3df083aSStefano Zampini       if (need_benign_correction) {
3023a3df083aSStefano Zampini         PetscScalar        *marr;
3024df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3025a3df083aSStefano Zampini 
3026a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
30275cbda25cSStefano Zampini         if (lda_rhs != n_R) {
30285cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
30295cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30305cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
30315cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30325cbda25cSStefano Zampini           }
30335cbda25cSStefano Zampini         } else {
3034a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3035a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30365cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3037a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3038a3df083aSStefano Zampini           }
30395cbda25cSStefano Zampini         }
3040a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3041a3df083aSStefano Zampini       }
304206656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
304306656605SStefano Zampini     } else {
304480677318SStefano Zampini       PetscScalar *marr;
304580677318SStefano Zampini 
304680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
304706656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3048ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3049ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
305006656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
305106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
305206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
305306656605SStefano Zampini       }
305480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
305506656605SStefano Zampini     }
305680677318SStefano Zampini     if (!pcbddc->switch_static) {
305780677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
305880677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
305980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
306080677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3061ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
306280677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
306380677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
306480677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
306580677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
306680677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
306780677318SStefano Zampini       }
306880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
306980677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
307072b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
307180677318SStefano Zampini     } else {
3072ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3073ffd830a3SStefano Zampini         IS dummy;
3074ffd830a3SStefano Zampini 
3075ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
307672b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3077ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3078ffd830a3SStefano Zampini       } else {
307980677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
308080677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3081ffd830a3SStefano Zampini       }
308225084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
308380677318SStefano Zampini     }
308480677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
308580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
308680677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
308706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
308806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
308980677318SStefano Zampini     if (isCHOL) {
309080677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
309180677318SStefano Zampini     } else {
309225084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
309380677318SStefano Zampini     }
309480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
309506656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
309625084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
309725084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
309825084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
309980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
310072b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
310172b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
310206656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
310306656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3104f4ddd8eeSStefano Zampini   }
3105fc227af8SStefano Zampini 
3106fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
310788ebb749SStefano Zampini   if (n_vertices) {
310806656605SStefano Zampini     IS is_aux;
31093a50541eSStefano Zampini 
3110b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
31116816873aSStefano Zampini       IS tis;
31126816873aSStefano Zampini 
31136816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
31146816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
31156816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
31166816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
31176816873aSStefano Zampini     } else {
31183a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
31196816873aSStefano Zampini     }
31209577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
31219577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
312204708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
312325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
312488ebb749SStefano Zampini   }
312588ebb749SStefano Zampini 
312688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3127f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
312806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
312906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
313006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
313106656605SStefano Zampini     }
3132f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
313306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
313406656605SStefano Zampini       PetscScalar *marray;
313506656605SStefano Zampini 
313606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
313706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3138f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3139f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3140f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3141f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3142f4ddd8eeSStefano Zampini     }
3143f4ddd8eeSStefano Zampini   }
314406656605SStefano Zampini 
3145f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
314606656605SStefano Zampini     PetscScalar *marray;
314788ebb749SStefano Zampini 
314806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31498eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
315006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
315188ebb749SStefano Zampini     }
31523301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
315306656605SStefano Zampini       n *= 2;
315488ebb749SStefano Zampini     }
315506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
315606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
315706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31588eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
315906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
316006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
316188ebb749SStefano Zampini     }
31623301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
316306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
31648eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
316506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
316606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
316788ebb749SStefano Zampini       }
316888ebb749SStefano Zampini     } else {
3169c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3170c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
31711b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3172c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3173c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3174c0553b1fSStefano Zampini       }
317588ebb749SStefano Zampini     }
317606656605SStefano Zampini   }
3177019a44ceSStefano Zampini 
317806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
31794f1b2e48SStefano Zampini   p0_lidx_I = NULL;
31804f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3181d12edf2fSStefano Zampini     const PetscInt *idxs;
3182d12edf2fSStefano Zampini 
3183d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
31844f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
31854f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
31864f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
31874f1b2e48SStefano Zampini     }
3188d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3189d12edf2fSStefano Zampini   }
3190d16cbb6bSStefano Zampini 
319106656605SStefano Zampini   /* vertices */
319206656605SStefano Zampini   if (n_vertices) {
319316f15bc4SStefano Zampini 
3194af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
319504708bb6SStefano Zampini 
319616f15bc4SStefano Zampini     if (n_R) {
319714393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
319806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
319916f15bc4SStefano Zampini       PetscScalar  *x,*y;
320004708bb6SStefano Zampini       PetscBool    isseqaij;
320106656605SStefano Zampini 
320221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
320314393ed6SStefano Zampini       if (need_benign_correction) {
320414393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
320514393ed6SStefano Zampini         IS                     is_p0;
320614393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
320714393ed6SStefano Zampini 
320814393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
320914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
321014393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3211af25d912SStefano 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);
321214393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
321314393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
321414393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
321514393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
321614393ed6SStefano Zampini       }
321714393ed6SStefano Zampini 
3218ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3219af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3220ffd830a3SStefano Zampini       } else {
3221ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3222ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3223ca92afb2SStefano Zampini         PetscInt       n;
3224ca92afb2SStefano Zampini         PetscBool      flg_row;
3225ffd830a3SStefano Zampini 
3226ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3227ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
32289d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3229ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3230ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3231ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3232ca92afb2SStefano Zampini           PetscInt j;
3233ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3234ffd830a3SStefano Zampini         }
3235ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3236ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3237ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3238ffd830a3SStefano Zampini       }
3239ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3240a3df083aSStefano Zampini       if (need_benign_correction) {
3241df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3242a3df083aSStefano Zampini         PetscScalar        *marr;
3243a3df083aSStefano Zampini 
3244a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
324514393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
324614393ed6SStefano Zampini 
324714393ed6SStefano Zampini                | 0 0  0 | (V)
324814393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
324914393ed6SStefano Zampini                | 0 0 -1 | (p0)
325014393ed6SStefano Zampini 
325114393ed6SStefano Zampini         */
3252df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
325314393ed6SStefano Zampini           const PetscScalar *vals;
325414393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
325514393ed6SStefano Zampini           PetscInt          n,j,nz;
325614393ed6SStefano Zampini 
3257df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3258df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
325914393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
326014393ed6SStefano Zampini           for (j=0;j<n;j++) {
326114393ed6SStefano Zampini             PetscScalar val = vals[j];
326214393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
326314393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
326414393ed6SStefano Zampini           }
326514393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3266df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
326714393ed6SStefano Zampini         }
326872b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
326972b8c272SStefano Zampini       }
327072b8c272SStefano Zampini       if (F) {
327114393ed6SStefano Zampini         /* need to correct the rhs */
327272b8c272SStefano Zampini         if (need_benign_correction) {
327372b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
327472b8c272SStefano Zampini           PetscScalar        *marr;
327572b8c272SStefano Zampini 
327672b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
32775cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32785cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32795cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32805cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
32815cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32825cbda25cSStefano Zampini             }
32835cbda25cSStefano Zampini           } else {
3284a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3285a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
32865cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3287a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3288a3df083aSStefano Zampini             }
32895cbda25cSStefano Zampini           }
3290a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3291a3df083aSStefano Zampini         }
329206656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
329314393ed6SStefano Zampini         /* need to correct the solution */
3294a3df083aSStefano Zampini         if (need_benign_correction) {
3295df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3296a3df083aSStefano Zampini           PetscScalar        *marr;
3297a3df083aSStefano Zampini 
3298a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
32995cbda25cSStefano Zampini           if (lda_rhs != n_R) {
33005cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
33015cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
33025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
33035cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
33045cbda25cSStefano Zampini             }
33055cbda25cSStefano Zampini           } else {
3306a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3307a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
33085cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3309a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3310a3df083aSStefano Zampini             }
33115cbda25cSStefano Zampini           }
3312a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3313a3df083aSStefano Zampini         }
331406656605SStefano Zampini       } else {
331506656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
331606656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3317ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3318ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
331906656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
332006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
332106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
332206656605SStefano Zampini         }
332306656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
332406656605SStefano Zampini       }
332580677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3326ffd830a3SStefano Zampini       /* S_VV and S_CV */
332706656605SStefano Zampini       if (n_constraints) {
332806656605SStefano Zampini         Mat B;
332980677318SStefano Zampini 
3330ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
333180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3332ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3333ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
333480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
333780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
333880677318SStefano Zampini         }
3339ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
334080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
334180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3342ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
334380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
334406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3345ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3346ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
334706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
334806656605SStefano Zampini       }
334904708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
335004708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3351511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
335204708bb6SStefano Zampini       }
3353ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3354ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3355ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3356ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3357ffd830a3SStefano Zampini       }
335806656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
335914393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
336014393ed6SStefano Zampini       if (need_benign_correction) {
3361df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
336214393ed6SStefano Zampini         PetscScalar      *marr,*sums;
336314393ed6SStefano Zampini 
336414393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
336514393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3366df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
336714393ed6SStefano Zampini           const PetscScalar *vals;
336814393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
336914393ed6SStefano Zampini           PetscInt          n,j,nz;
337014393ed6SStefano Zampini 
3371df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3372df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
337314393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
337414393ed6SStefano Zampini             PetscInt k;
337514393ed6SStefano Zampini             sums[j] = 0.;
337614393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
337714393ed6SStefano Zampini           }
337814393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
337914393ed6SStefano Zampini           for (j=0;j<n;j++) {
338014393ed6SStefano Zampini             PetscScalar val = vals[j];
338114393ed6SStefano Zampini             PetscInt k;
338214393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
338314393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
338414393ed6SStefano Zampini             }
338514393ed6SStefano Zampini           }
338614393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3387df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
338814393ed6SStefano Zampini         }
338914393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
339014393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
339114393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
339214393ed6SStefano Zampini       }
339380677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
339406656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
339506656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
339606656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
339706656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
339806656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
339906656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
340006656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3401d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3402019a44ceSStefano Zampini     } else {
3403d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3404d16cbb6bSStefano Zampini     }
340521eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3406d16cbb6bSStefano Zampini 
340706656605SStefano Zampini     /* coarse basis functions */
340806656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
340916f15bc4SStefano Zampini       PetscScalar *y;
341016f15bc4SStefano Zampini 
3411ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
341206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
341306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
341406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341606656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
341706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
341806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
341906656605SStefano Zampini 
342006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34214f1b2e48SStefano Zampini         PetscInt j;
34224f1b2e48SStefano Zampini 
342306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
342406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
342506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34284f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
342906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
343006656605SStefano Zampini       }
343106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
343206656605SStefano Zampini     }
343304708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
343404708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
343506656605SStefano Zampini   }
34365cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
343706656605SStefano Zampini 
343806656605SStefano Zampini   if (n_constraints) {
343906656605SStefano Zampini     Mat B;
344006656605SStefano Zampini 
3441ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
344206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
344380677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
344406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
344506656605SStefano Zampini     if (n_vertices) {
344680677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
344780677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
344880677318SStefano Zampini       } else {
344980677318SStefano Zampini         Mat S_VCt;
345080677318SStefano Zampini 
3451ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3452ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
345372b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3454ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3455ffd830a3SStefano Zampini         }
345680677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
345780677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
345880677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
345980677318SStefano Zampini       }
346006656605SStefano Zampini     }
346106656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
346206656605SStefano Zampini     /* coarse basis functions */
346306656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
346406656605SStefano Zampini       PetscScalar *y;
346506656605SStefano Zampini 
3466ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
346706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
346806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
346906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
347206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
347306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34744f1b2e48SStefano Zampini         PetscInt j;
34754f1b2e48SStefano Zampini 
347606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
347706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
347806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
348006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34814f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
348206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
348306656605SStefano Zampini       }
348406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
348506656605SStefano Zampini     }
348606656605SStefano Zampini   }
348780677318SStefano Zampini   if (n_constraints) {
348880677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
348980677318SStefano Zampini   }
34904f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
349172b8c272SStefano Zampini 
349272b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
349372b8c272SStefano Zampini   if (pcbddc->benign_n) {
349472b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
349572b8c272SStefano Zampini     IS          is_dummy;
349672b8c272SStefano Zampini     PetscScalar *data;
349772b8c272SStefano Zampini     PetscInt    j;
349872b8c272SStefano Zampini 
349972b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
350072b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
350172b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
350272b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
350386c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
350472b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
350572b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
350672b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
350772b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
350872b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
350972b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
351072b8c272SStefano Zampini       }
351172b8c272SStefano Zampini     }
351272b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
351372b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
351472b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
351572b8c272SStefano Zampini   }
3516019a44ceSStefano Zampini 
351706656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
35183301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3519ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3520ffd830a3SStefano Zampini     PetscScalar *marray;
352106656605SStefano Zampini 
352206656605SStefano Zampini     if (n_constraints) {
3523ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
352406656605SStefano Zampini 
3525af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
352606656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3527ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
352816f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
352906656605SStefano Zampini       if (n_vertices) {
3530ffd830a3SStefano Zampini         Mat S_VCT;
353106656605SStefano Zampini 
353206656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3533ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
353416f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
353506656605SStefano Zampini       }
3536ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
35375b782168SStefano Zampini     } else {
35385b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
353906656605SStefano Zampini     }
354016f15bc4SStefano Zampini     if (n_vertices && n_R) {
3541ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3542ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3543ffd830a3SStefano Zampini       PetscInt       n;
3544ffd830a3SStefano Zampini       PetscBool      flg_row;
354506656605SStefano Zampini 
3546ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3547af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3548ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3549ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3550ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3551ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3552ffd830a3SStefano Zampini         PetscInt j;
3553ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3554ffd830a3SStefano Zampini       }
3555ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3556ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3557ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
355806656605SStefano Zampini     }
355906656605SStefano Zampini 
3560ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3561ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3562ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3563ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3564ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
356506656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
356606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
356706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
356806656605SStefano Zampini     }
3569ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
35705b782168SStefano Zampini     if (B_C) {
3571ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3572ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3573ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3574ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3575ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3576ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3577ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
357806656605SStefano Zampini       }
3579ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
35805b782168SStefano Zampini     }
358106656605SStefano Zampini     /* coarse basis functions */
358206656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
358306656605SStefano Zampini       PetscScalar *y;
358406656605SStefano Zampini 
3585ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
358606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
358706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
358806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
358906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
359006656605SStefano Zampini       if (i<n_vertices) {
359106656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
359206656605SStefano Zampini       }
359306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
359406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
359506656605SStefano Zampini 
359606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
359706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
359806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
359906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
360006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
360106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
360206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
360306656605SStefano Zampini       }
360406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
360506656605SStefano Zampini     }
3606ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3607ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
360806656605SStefano Zampini   }
3609d62866d3SStefano Zampini   /* free memory */
361088ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
361106656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
361206656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
361306656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
361406656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3615d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3616d62866d3SStefano Zampini   if (n_vertices) {
3617d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3618d62866d3SStefano Zampini   }
3619d62866d3SStefano Zampini   if (n_constraints) {
3620d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3621d62866d3SStefano Zampini   }
362288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
362388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
362488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3625d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
362688ebb749SStefano Zampini     Mat         coarse_sub_mat;
362725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
362888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
362988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
363088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
36318bec7fa6SStefano Zampini     Mat         C_B,CPHI;
36328bec7fa6SStefano Zampini     IS          is_dummy;
36338bec7fa6SStefano Zampini     Vec         mones;
363488ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
363588ebb749SStefano Zampini     PetscReal   real_value;
363688ebb749SStefano Zampini 
3637a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3638a3df083aSStefano Zampini       Mat A;
3639a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3640a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3641a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3642a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3643a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3644a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3645a3df083aSStefano Zampini     } else {
364688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
364788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
364888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
364988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3650a3df083aSStefano Zampini     }
365188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
365288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3653ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
365488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
365588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
365688ebb749SStefano Zampini     }
365788ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
365888ebb749SStefano Zampini 
365925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36603301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
366125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3662ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
366388ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
366588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366688ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
366888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
367188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
367488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367588ebb749SStefano Zampini     } else {
367688ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
367788ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
367888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
368088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
368188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
368288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
368388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
368488ebb749SStefano Zampini     }
368588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3688511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
36894f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3690fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3691d12edf2fSStefano Zampini       PetscScalar *data,*data2;
36924f1b2e48SStefano Zampini       PetscInt    j;
3693d12edf2fSStefano Zampini 
36944f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3695fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3696d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
369786c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3698d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3699d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
37004f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
37014f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3702d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
37034f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
37044f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
37054f1b2e48SStefano Zampini         }
3706d12edf2fSStefano Zampini       }
3707d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3708d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3709d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3710d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3711d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3712d12edf2fSStefano Zampini     }
3713d12edf2fSStefano Zampini #if 0
3714d12edf2fSStefano Zampini   {
3715d12edf2fSStefano Zampini     PetscViewer viewer;
3716d12edf2fSStefano Zampini     char filename[256];
3717ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3718d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3719d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3720ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3721ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3722ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3723d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
372472b8c272SStefano Zampini     if (save_change) {
372572b8c272SStefano Zampini       Mat phi_B;
372672b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
372772b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
372872b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
372972b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
373072b8c272SStefano Zampini     } else {
3731ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3732ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
373372b8c272SStefano Zampini     }
3734ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3735ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3736ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3737ffd830a3SStefano Zampini     }
3738ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3739ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3740ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3741ffd830a3SStefano Zampini     }
374272b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3743ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3744ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3745ffd830a3SStefano Zampini     }
3746d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3747d12edf2fSStefano Zampini   }
3748d12edf2fSStefano Zampini #endif
374981d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
37508bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
37511575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
375206656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
37538bec7fa6SStefano Zampini 
37548bec7fa6SStefano Zampini     /* check constraints */
3755a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3756a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
37574f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
37588bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3759a00504b5SStefano Zampini     } else {
3760a00504b5SStefano Zampini       PetscScalar *data;
3761a00504b5SStefano Zampini       Mat         tmat;
3762a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3763a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3764a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3765a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3766a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3767a00504b5SStefano Zampini     }
37688bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
37698bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
37708bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
37718bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3772bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3773ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3774bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3775bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3776bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3777bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3778bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
377988ebb749SStefano Zampini     }
37808bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
37818bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
37828bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37838bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
378425084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
378588ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
378688ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
378788ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
378888ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
378988ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
379088ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
379188ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
379288ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
379388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
379488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3795ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
379688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
379788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
379888ebb749SStefano Zampini     }
379988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
380088ebb749SStefano Zampini   }
38018629588bSStefano Zampini   /* get back data */
38028629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
380388ebb749SStefano Zampini   PetscFunctionReturn(0);
380488ebb749SStefano Zampini }
380588ebb749SStefano Zampini 
380688ebb749SStefano Zampini #undef __FUNCT__
3807d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3808d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3809aa0d41d4SStefano Zampini {
3810d65f70fdSStefano Zampini   Mat            *work_mat;
3811d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3812d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3813c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3814aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3815aa0d41d4SStefano Zampini 
3816aa0d41d4SStefano Zampini   PetscFunctionBegin;
3817d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3818d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3819d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3820d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3821aa0d41d4SStefano Zampini 
3822d65f70fdSStefano Zampini   if (!rsorted) {
3823906d46d4SStefano Zampini     const PetscInt *idxs;
3824906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3825aa0d41d4SStefano Zampini 
3826d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3827d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3828d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3829d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3830aa0d41d4SStefano Zampini     }
3831d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3832d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3833d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3834d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3835aa0d41d4SStefano Zampini     }
3836d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3837d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3838d65f70fdSStefano Zampini   } else {
3839d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3840d65f70fdSStefano Zampini     isrow_s = isrow;
3841aa0d41d4SStefano Zampini   }
3842906d46d4SStefano Zampini 
3843d65f70fdSStefano Zampini   if (!csorted) {
3844d65f70fdSStefano Zampini     if (isrow == iscol) {
3845d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3846d65f70fdSStefano Zampini       iscol_s = isrow_s;
3847d65f70fdSStefano Zampini     } else {
3848d65f70fdSStefano Zampini       const PetscInt *idxs;
3849d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3850906d46d4SStefano Zampini 
3851d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3852d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3853d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3854d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3855d65f70fdSStefano Zampini       }
3856d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3857d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3858d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3859d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3860d65f70fdSStefano Zampini       }
3861d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3862d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3863d65f70fdSStefano Zampini     }
3864d65f70fdSStefano Zampini   } else {
3865d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3866d65f70fdSStefano Zampini     iscol_s = iscol;
3867d65f70fdSStefano Zampini   }
3868d65f70fdSStefano Zampini 
3869d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3870d65f70fdSStefano Zampini 
3871d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3872906d46d4SStefano Zampini     Mat      new_mat;
3873d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3874906d46d4SStefano Zampini 
3875d65f70fdSStefano Zampini     if (!rsorted) {
3876d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3877d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3878d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3879d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3880906d46d4SStefano Zampini       }
3881d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3882d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3883d65f70fdSStefano Zampini     } else {
3884d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3885906d46d4SStefano Zampini     }
3886d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3887d65f70fdSStefano Zampini 
3888d65f70fdSStefano Zampini     if (!csorted) {
3889d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3890d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3891d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3892d65f70fdSStefano Zampini       } else {
3893d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3894d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3895d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3896d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3897d65f70fdSStefano Zampini         }
3898d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3899d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3900d65f70fdSStefano Zampini       }
3901d65f70fdSStefano Zampini     } else {
3902d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3903d65f70fdSStefano Zampini     }
3904d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3905d65f70fdSStefano Zampini 
3906d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3907d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3908d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3909d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3910d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3911d65f70fdSStefano Zampini   }
3912d65f70fdSStefano Zampini 
3913d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3914d65f70fdSStefano Zampini   *B = work_mat[0];
3915d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3916d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3917d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3918d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3919d65f70fdSStefano Zampini }
3920d65f70fdSStefano Zampini 
3921d65f70fdSStefano Zampini #undef __FUNCT__
39225e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
39235e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3924aa0d41d4SStefano Zampini {
3925aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
39265e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3927d65f70fdSStefano Zampini   Mat            new_mat;
39285e8657edSStefano Zampini   IS             is_local,is_global;
3929d65f70fdSStefano Zampini   PetscInt       local_size;
3930d65f70fdSStefano Zampini   PetscBool      isseqaij;
3931aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3932aa0d41d4SStefano Zampini 
3933aa0d41d4SStefano Zampini   PetscFunctionBegin;
3934aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
39355e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
39365e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3937b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3938aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3939d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3940aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3941906d46d4SStefano Zampini 
3942906d46d4SStefano Zampini   /* check */
3943906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3944906d46d4SStefano Zampini     Vec       x,x_change;
3945906d46d4SStefano Zampini     PetscReal error;
3946906d46d4SStefano Zampini 
39475e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3948906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
39495e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3950e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3951e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3952d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3953e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3954e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3955906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3956906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3957906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3958906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3959906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3960906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3961906d46d4SStefano Zampini   }
3962906d46d4SStefano Zampini 
396322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
39649b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
396522d5777bSStefano Zampini   if (isseqaij) {
3966a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3967a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3968aa0d41d4SStefano Zampini   } else {
3969a00504b5SStefano Zampini     Mat work_mat;
39701cf9b237SStefano Zampini 
3971a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3972aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3973a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
39741d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3975aa0d41d4SStefano Zampini   }
39763301b35fSStefano Zampini   if (matis->A->symmetric_set) {
39773301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3978e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39793301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3980e496cd5dSStefano Zampini #endif
39813301b35fSStefano Zampini   }
3982d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3983aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3984aa0d41d4SStefano Zampini }
3985aa0d41d4SStefano Zampini 
3986aa0d41d4SStefano Zampini #undef __FUNCT__
3987a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
39888ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3989a64d13efSStefano Zampini {
3990a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3991a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3992d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
399353892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
39943a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
39953a50541eSStefano Zampini   PetscInt        vbs,bs;
39966816873aSStefano Zampini   PetscBT         bitmask=NULL;
3997a64d13efSStefano Zampini   PetscErrorCode  ierr;
3998a64d13efSStefano Zampini 
3999a64d13efSStefano Zampini   PetscFunctionBegin;
4000b23d619eSStefano Zampini   /*
4001b23d619eSStefano Zampini     No need to setup local scatters if
4002b23d619eSStefano Zampini       - primal space is unchanged
4003b23d619eSStefano Zampini         AND
4004b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4005b23d619eSStefano Zampini         AND
4006b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4007b23d619eSStefano Zampini   */
4008b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4009f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4010f4ddd8eeSStefano Zampini   }
4011f4ddd8eeSStefano Zampini   /* destroy old objects */
4012f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4013f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4014f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4015a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4016b371cd4fSStefano Zampini   n_B = pcis->n_B;
4017b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4018b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
40193a50541eSStefano Zampini 
4020a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
40216816873aSStefano Zampini 
402253892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4023b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4024854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4025a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4026a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
40270e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4028a64d13efSStefano Zampini     }
4029a64d13efSStefano Zampini 
4030a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
40314641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
40326816873aSStefano Zampini         idx_R_local[n_R++] = i;
4033a64d13efSStefano Zampini       }
4034a64d13efSStefano Zampini     }
4035df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4036df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
40376816873aSStefano Zampini 
4038df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4039df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
40406816873aSStefano Zampini   }
40413a50541eSStefano Zampini 
40423a50541eSStefano Zampini   /* Block code */
40433a50541eSStefano Zampini   vbs = 1;
40443a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
40453a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
40463a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
40473a50541eSStefano Zampini     PetscInt  *vary;
4048b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4049785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
40503a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4051d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4052d3df7717SStefano 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 */
40530e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4054d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
40553a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
40563a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
40573a50541eSStefano Zampini           break;
40583a50541eSStefano Zampini         }
40593a50541eSStefano Zampini       }
4060d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4061d3df7717SStefano Zampini     } else {
4062d3df7717SStefano Zampini       /* Verify directly the R set */
4063d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4064d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4065d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4066d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4067d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4068d3df7717SStefano Zampini             break;
4069d3df7717SStefano Zampini           }
4070d3df7717SStefano Zampini         }
4071d3df7717SStefano Zampini       }
4072d3df7717SStefano Zampini     }
40733a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
40743a50541eSStefano Zampini       vbs = bs;
40753a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
40763a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
40773a50541eSStefano Zampini       }
40783a50541eSStefano Zampini     }
40793a50541eSStefano Zampini   }
40803a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4081b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4082df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
408353892102SStefano Zampini 
4084df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4085df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
408653892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4087df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
408853892102SStefano Zampini   } else {
40893a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
409053892102SStefano Zampini   }
4091a64d13efSStefano Zampini 
4092a64d13efSStefano Zampini   /* print some info if requested */
4093a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4094a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4095a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40961575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4097a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4098a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
40994f1b2e48SStefano 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);
4100a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4101a64d13efSStefano Zampini   }
4102a64d13efSStefano Zampini 
4103a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4104b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
41056816873aSStefano Zampini     IS       is_aux1,is_aux2;
41066816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
41076816873aSStefano Zampini 
41083a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4109854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4110854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4111a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
41124641a718SStefano Zampini     for (i=0; i<n_D; i++) {
41134641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
41144641a718SStefano Zampini     }
4115a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4116a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
41174641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
41184641a718SStefano Zampini         aux_array1[j++] = i;
4119a64d13efSStefano Zampini       }
4120a64d13efSStefano Zampini     }
4121a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4122a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4123a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
41244641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
41254641a718SStefano Zampini         aux_array2[j++] = i;
4126a64d13efSStefano Zampini       }
4127a64d13efSStefano Zampini     }
4128a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4129a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4130a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4131a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4132a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4133a64d13efSStefano Zampini 
41348eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4135785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4136a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
41374641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
41384641a718SStefano Zampini           aux_array1[j++] = i;
4139a64d13efSStefano Zampini         }
4140a64d13efSStefano Zampini       }
4141a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4142a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4143a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4144a64d13efSStefano Zampini     }
41454641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
41463a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4147d62866d3SStefano Zampini   } else {
4148df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
41496816873aSStefano Zampini     IS                 tis;
41506816873aSStefano Zampini     PetscInt           schur_size;
41516816873aSStefano Zampini 
4152df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
41536816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4154df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
41556816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
41566816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41576816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
41586816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
41596816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4160d62866d3SStefano Zampini     }
4161d62866d3SStefano Zampini   }
4162a64d13efSStefano Zampini   PetscFunctionReturn(0);
4163a64d13efSStefano Zampini }
4164a64d13efSStefano Zampini 
4165304d26faSStefano Zampini 
4166304d26faSStefano Zampini #undef __FUNCT__
4167304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4168684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4169304d26faSStefano Zampini {
4170304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4171304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4172304d26faSStefano Zampini   PC             pc_temp;
4173304d26faSStefano Zampini   Mat            A_RR;
4174f4ddd8eeSStefano Zampini   MatReuse       reuse;
4175304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4176304d26faSStefano Zampini   PetscReal      value;
417704708bb6SStefano Zampini   PetscInt       n_D,n_R;
4178c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4179304d26faSStefano Zampini   PetscErrorCode ierr;
4180e604994aSStefano Zampini   /* prefixes stuff */
4181312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4182e604994aSStefano Zampini   size_t         len;
4183304d26faSStefano Zampini 
4184304d26faSStefano Zampini   PetscFunctionBegin;
4185304d26faSStefano Zampini 
4186e604994aSStefano Zampini   /* compute prefixes */
4187e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4188e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4189e604994aSStefano Zampini   if (!pcbddc->current_level) {
4190e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4191e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4192e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4193e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4194e604994aSStefano Zampini   } else {
4195e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4196312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4197e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4198e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4199312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4200312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
420134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
420234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4203e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4204e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4205e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4206e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4207e604994aSStefano Zampini   }
4208e604994aSStefano Zampini 
4209304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4210684f6988SStefano Zampini   if (dirichlet) {
4211d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4212450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
42139a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4214450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4215a3df083aSStefano Zampini         Mat    A_IIn;
4216a3df083aSStefano Zampini 
4217a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4218a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4219a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4220a3df083aSStefano Zampini       }
4221450f8f5eSStefano Zampini     }
42223301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
42233301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4224964fefecSStefano Zampini     }
4225ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4226964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4227304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4228304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4229304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4230304d26faSStefano Zampini       /* default */
4231304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4232e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
42339577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4234304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
42359577ea80SStefano Zampini       if (issbaij) {
42369577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
42379577ea80SStefano Zampini       } else {
4238304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
42399577ea80SStefano Zampini       }
4240304d26faSStefano Zampini       /* Allow user's customization */
4241304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4242304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4243304d26faSStefano Zampini     }
4244d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4245b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4246df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4247d62866d3SStefano Zampini 
4248df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4249d5574798SStefano Zampini     }
4250304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4251304d26faSStefano Zampini     if (!n_D) {
4252304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4253304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4254304d26faSStefano Zampini     }
4255304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4256304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4257304d26faSStefano Zampini     /* set ksp_D into pcis data */
4258304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4259304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4260304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4261684f6988SStefano Zampini   }
4262304d26faSStefano Zampini 
4263304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4264684f6988SStefano Zampini   A_RR = 0;
4265684f6988SStefano Zampini   if (neumann) {
4266d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
426704708bb6SStefano Zampini     PetscInt        ibs,mbs;
426804708bb6SStefano Zampini     PetscBool       issbaij;
426904708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4270f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
42718ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4272f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4273f4ddd8eeSStefano Zampini       PetscInt nn_R;
427481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4275f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4276f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4277f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4278f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4279f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4280f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4281f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4282727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4283f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4284f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4285f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4286f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4287f4ddd8eeSStefano Zampini         }
4288f4ddd8eeSStefano Zampini       }
4289f4ddd8eeSStefano Zampini       /* last check */
4290d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4291f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4292f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4293f4ddd8eeSStefano Zampini       }
4294f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4295f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4296f4ddd8eeSStefano Zampini     }
4297a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4298af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4299af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
430004708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
430104708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
430204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
430304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
430404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4305af732b37SStefano Zampini       } else {
4306511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
43076816873aSStefano Zampini       }
430804708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
430904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
431004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
431104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
431204708bb6SStefano Zampini       } else {
4313511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
431404708bb6SStefano Zampini       }
431504708bb6SStefano Zampini     }
4316a00504b5SStefano Zampini     /* extract A_RR */
4317b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4318a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4319a00504b5SStefano Zampini 
4320a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
432116e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4322a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
432316e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
432416e386b8SStefano Zampini         } else {
4325a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4326a00504b5SStefano Zampini         }
4327a00504b5SStefano Zampini       } else {
4328a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4329a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4330a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4331a00504b5SStefano Zampini       }
4332a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4333f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
433416e386b8SStefano Zampini     }
43353301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
43363301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
43376816873aSStefano Zampini     }
4338f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4339304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4340304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4341304d26faSStefano Zampini       /* default */
4342304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4343e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4344304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
43459577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
43469577ea80SStefano Zampini       if (issbaij) {
43479577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
43489577ea80SStefano Zampini       } else {
4349304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
43509577ea80SStefano Zampini       }
4351304d26faSStefano Zampini       /* Allow user's customization */
4352304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4353304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4354304d26faSStefano Zampini     }
4355304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4356304d26faSStefano Zampini     if (!n_R) {
4357304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4358304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4359304d26faSStefano Zampini     }
43605cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4361df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4362b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4363df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4364d62866d3SStefano Zampini 
4365df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4366d62866d3SStefano Zampini     }
4367304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4368304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4369684f6988SStefano Zampini   }
4370304d26faSStefano Zampini 
4371684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4372684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43731575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4374684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4375684f6988SStefano Zampini   }
4376c7017625SStefano Zampini 
4377c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4378c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4379c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4380c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4381c7017625SStefano Zampini   }
4382c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4383c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4384c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4385c7017625SStefano Zampini   }
4386c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4387c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4388c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4389c7017625SStefano Zampini   }
4390c7017625SStefano Zampini 
4391c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4392c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4393684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
43940fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
43950fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
43960fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
43970fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
43980fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4399e604994aSStefano 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);
4400c7017625SStefano Zampini       if (check_corr[0]) {
4401c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4402c7017625SStefano Zampini       }
4403304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4404304d26faSStefano Zampini     }
4405684f6988SStefano Zampini     if (neumann) { /* Neumann */
44060fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
44070fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
44080fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
44090fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
44100fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4411e604994aSStefano 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);
4412c7017625SStefano Zampini       if (check_corr[1]) {
4413c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4414c7017625SStefano Zampini       }
4415304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4416304d26faSStefano Zampini     }
4417684f6988SStefano Zampini   }
44185cbda25cSStefano Zampini   /* free Neumann problem's matrix */
44195cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4420304d26faSStefano Zampini   PetscFunctionReturn(0);
4421304d26faSStefano Zampini }
4422304d26faSStefano Zampini 
4423304d26faSStefano Zampini #undef __FUNCT__
4424ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
442580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4426674ae819SStefano Zampini {
4427674ae819SStefano Zampini   PetscErrorCode  ierr;
4428674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4429be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4430b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4431674ae819SStefano Zampini 
4432674ae819SStefano Zampini   PetscFunctionBegin;
4433b334f244SStefano Zampini   if (!reuse_solver) {
443480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
443520c7b377SStefano Zampini   }
443680677318SStefano Zampini   if (!pcbddc->switch_static) {
443780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
443880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
443980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
444020c7b377SStefano Zampini     }
4441b334f244SStefano Zampini     if (!reuse_solver) {
444280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444420c7b377SStefano Zampini     } else {
4445df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4446be83ff47SStefano Zampini 
4447df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4448df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
444920c7b377SStefano Zampini     }
4450be83ff47SStefano Zampini   } else {
445180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
445680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
445780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
445880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4460674ae819SStefano Zampini     }
4461674ae819SStefano Zampini   }
4462b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
446380677318SStefano Zampini     if (applytranspose) {
446480677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446580677318SStefano Zampini     } else {
446680677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446780677318SStefano Zampini     }
4468be83ff47SStefano Zampini   } else {
4469df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4470be83ff47SStefano Zampini 
4471be83ff47SStefano Zampini     if (applytranspose) {
4472df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4473be83ff47SStefano Zampini     } else {
4474df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4475be83ff47SStefano Zampini     }
4476be83ff47SStefano Zampini   }
447780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
447880677318SStefano Zampini   if (!pcbddc->switch_static) {
4479b334f244SStefano Zampini     if (!reuse_solver) {
448080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4482be83ff47SStefano Zampini     } else {
4483df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4484be83ff47SStefano Zampini 
4485df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4486df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4487be83ff47SStefano Zampini     }
448880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
448980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
449080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
449180677318SStefano Zampini     }
449280677318SStefano Zampini   } else {
449380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
449880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
449980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
450080677318SStefano Zampini     }
450180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4505674ae819SStefano Zampini   }
4506674ae819SStefano Zampini   PetscFunctionReturn(0);
4507674ae819SStefano Zampini }
4508674ae819SStefano Zampini 
4509dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4510674ae819SStefano Zampini #undef __FUNCT__
4511674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4512dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4513674ae819SStefano Zampini {
4514674ae819SStefano Zampini   PetscErrorCode ierr;
4515674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4516674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4517674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4518674ae819SStefano Zampini 
4519674ae819SStefano Zampini   PetscFunctionBegin;
4520dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
45214fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4522dc359a40SStefano Zampini     if (applytranspose) {
4523674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
45248eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4525dc359a40SStefano Zampini     } else {
4526674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4527674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
452815aaf578SStefano Zampini     }
45294fee134fSStefano Zampini   } else {
45304fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
45314fee134fSStefano Zampini   }
4532efc2fbd9SStefano Zampini 
4533efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
45344f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4535efc2fbd9SStefano Zampini     PetscScalar *array;
45364f1b2e48SStefano Zampini     PetscInt    j;
4537efc2fbd9SStefano Zampini 
4538efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
45394f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4540efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4541efc2fbd9SStefano Zampini   }
4542efc2fbd9SStefano Zampini 
454312edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
454412edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
454512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454712edc857SStefano Zampini 
45489f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
454912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
455051694757SStefano Zampini     Mat          coarse_mat;
4551964fefecSStefano Zampini     Vec          rhs,sol;
455251694757SStefano Zampini     MatNullSpace nullsp;
455327b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4554964fefecSStefano Zampini 
455527b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
455627b6a85dSStefano Zampini       PC        coarse_pc;
455727b6a85dSStefano Zampini 
455827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
455927b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
456027b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
456127b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
456227b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
456327b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
45643bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
456527b6a85dSStefano Zampini       }
456627b6a85dSStefano Zampini     }
4567964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4568964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
456951694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
457051694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
457151694757SStefano Zampini     if (nullsp) {
457251694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
457351694757SStefano Zampini     }
457412edc857SStefano Zampini     if (applytranspose) {
45759a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4576964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
45772701bc32SStefano Zampini     } else {
45781f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
45792701bc32SStefano Zampini         PC        coarse_pc;
45802701bc32SStefano Zampini 
45812701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
45822701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
45833e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
45842701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
458512edc857SStefano Zampini       } else {
4586964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
458712edc857SStefano Zampini       }
45882701bc32SStefano Zampini     }
45891d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
459027b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
459127b6a85dSStefano Zampini       PC        coarse_pc;
459227b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
459327b6a85dSStefano Zampini 
459427b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
459527b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
459627b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
45973bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
459827b6a85dSStefano Zampini     }
459951694757SStefano Zampini     if (nullsp) {
460051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
460151694757SStefano Zampini     }
460212edc857SStefano Zampini   }
4603674ae819SStefano Zampini 
4604674ae819SStefano Zampini   /* Local solution on R nodes */
46054fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
460680677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
46079f00e9b4SStefano Zampini   }
46089f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
46099f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
461012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4611674ae819SStefano Zampini 
46124fee134fSStefano Zampini   /* Sum contributions from the two levels */
46134fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4614dc359a40SStefano Zampini     if (applytranspose) {
4615dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4616dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4617dc359a40SStefano Zampini     } else {
4618674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
46198eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4620dc359a40SStefano Zampini     }
4621efc2fbd9SStefano Zampini     /* store p0 */
46224f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4623efc2fbd9SStefano Zampini       PetscScalar *array;
46244f1b2e48SStefano Zampini       PetscInt    j;
4625efc2fbd9SStefano Zampini 
4626efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
46274f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4628efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4629efc2fbd9SStefano Zampini     }
46304fee134fSStefano Zampini   } else { /* expand the coarse solution */
46314fee134fSStefano Zampini     if (applytranspose) {
46324fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46334fee134fSStefano Zampini     } else {
46344fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46354fee134fSStefano Zampini     }
46364fee134fSStefano Zampini   }
4637674ae819SStefano Zampini   PetscFunctionReturn(0);
4638674ae819SStefano Zampini }
4639674ae819SStefano Zampini 
4640674ae819SStefano Zampini #undef __FUNCT__
4641674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
464212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4643674ae819SStefano Zampini {
4644674ae819SStefano Zampini   PetscErrorCode ierr;
4645674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
464658da7f69SStefano Zampini   PetscScalar    *array;
464712edc857SStefano Zampini   Vec            from,to;
4648674ae819SStefano Zampini 
4649674ae819SStefano Zampini   PetscFunctionBegin;
465012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
465112edc857SStefano Zampini     from = pcbddc->coarse_vec;
465212edc857SStefano Zampini     to = pcbddc->vec1_P;
465312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
465412edc857SStefano Zampini       Vec tvec;
465558da7f69SStefano Zampini 
465658da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465758da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
465812edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465958da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
466058da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
466158da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
466212edc857SStefano Zampini     }
466312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
466412edc857SStefano Zampini     from = pcbddc->vec1_P;
466512edc857SStefano Zampini     to = pcbddc->coarse_vec;
466612edc857SStefano Zampini   }
466712edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4668674ae819SStefano Zampini   PetscFunctionReturn(0);
4669674ae819SStefano Zampini }
4670674ae819SStefano Zampini 
4671674ae819SStefano Zampini #undef __FUNCT__
4672674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
467312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4674674ae819SStefano Zampini {
4675674ae819SStefano Zampini   PetscErrorCode ierr;
4676674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
467758da7f69SStefano Zampini   PetscScalar    *array;
467812edc857SStefano Zampini   Vec            from,to;
4679674ae819SStefano Zampini 
4680674ae819SStefano Zampini   PetscFunctionBegin;
468112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
468212edc857SStefano Zampini     from = pcbddc->coarse_vec;
468312edc857SStefano Zampini     to = pcbddc->vec1_P;
468412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
468512edc857SStefano Zampini     from = pcbddc->vec1_P;
468612edc857SStefano Zampini     to = pcbddc->coarse_vec;
468712edc857SStefano Zampini   }
468812edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
468912edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
469012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
469112edc857SStefano Zampini       Vec tvec;
469258da7f69SStefano Zampini 
469312edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
469458da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
469558da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
469658da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
469758da7f69SStefano Zampini     }
469858da7f69SStefano Zampini   } else {
469958da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
470058da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
470112edc857SStefano Zampini     }
470212edc857SStefano Zampini   }
4703674ae819SStefano Zampini   PetscFunctionReturn(0);
4704674ae819SStefano Zampini }
4705674ae819SStefano Zampini 
4706984c4197SStefano Zampini /* uncomment for testing purposes */
4707984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4708674ae819SStefano Zampini #undef __FUNCT__
4709674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4710674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4711674ae819SStefano Zampini {
4712674ae819SStefano Zampini   PetscErrorCode    ierr;
4713674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4714674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4715674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4716984c4197SStefano Zampini   /* one and zero */
4717984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4718984c4197SStefano Zampini   /* space to store constraints and their local indices */
47199162d606SStefano Zampini   PetscScalar       *constraints_data;
47209162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
47219162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
47229162d606SStefano Zampini   PetscInt          *constraints_n;
4723984c4197SStefano Zampini   /* iterators */
4724b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4725984c4197SStefano Zampini   /* BLAS integers */
4726e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4727e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4728c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4729727cdba6SStefano Zampini   /* reuse */
47300e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
47310e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4732984c4197SStefano Zampini   /* change of basis */
4733b3d85658SStefano Zampini   PetscBool         qr_needed;
47349162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4735984c4197SStefano Zampini   /* auxiliary stuff */
473664efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
47378a0068c3SStefano Zampini   PetscInt          ncc;
4738984c4197SStefano Zampini   /* some quantities */
473945a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4740a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4741984c4197SStefano Zampini 
4742674ae819SStefano Zampini   PetscFunctionBegin;
47438e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
47448e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47458e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
474616909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4747088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4748088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
47490e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
47500e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
47510e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47520e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47530e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4754088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4755cf5a6209SStefano Zampini 
4756cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
47579162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4758cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4759cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4760cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4761cf5a6209SStefano Zampini     PetscScalar  *array;
4762cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4763cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4764674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4765b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4766674ae819SStefano Zampini     PetscScalar  *work;
4767674ae819SStefano Zampini     PetscReal    *singular_vals;
4768674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4769674ae819SStefano Zampini     PetscReal    *rwork;
4770674ae819SStefano Zampini #endif
4771674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4772674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4773674ae819SStefano Zampini #else
4774964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4775964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4776674ae819SStefano Zampini #endif
4777674ae819SStefano Zampini 
4778674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4779d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4780e4d548c7SStefano Zampini     /* print some info */
47811f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4782e4d548c7SStefano Zampini       PetscInt nv;
4783e4d548c7SStefano Zampini 
4784c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4785e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4786e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4787e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4788e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4789e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4790e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4791e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4792e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4793e4d548c7SStefano Zampini     }
4794e4d548c7SStefano Zampini 
4795d06fc5fdSStefano Zampini     /* free unneeded index sets */
4796d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4797d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4798674ae819SStefano Zampini     }
4799d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4800d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4801d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4802d06fc5fdSStefano Zampini       }
4803d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4804d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4805d06fc5fdSStefano Zampini     }
4806d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4807d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4808d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4809d06fc5fdSStefano Zampini       }
4810d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4811d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4812d06fc5fdSStefano Zampini     }
481370022509SStefano Zampini 
4814674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4815674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4816674ae819SStefano Zampini     if (nearnullsp) {
4817674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4818f4ddd8eeSStefano Zampini       /* remove any stored info */
4819f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4820f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4821f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4822f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4823f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4824473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4825f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4826f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4827f4ddd8eeSStefano Zampini       }
4828984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4829984c4197SStefano Zampini       nnsp_size = 0;
4830674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4831674ae819SStefano Zampini     }
4832984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4833984c4197SStefano Zampini     max_constraints = nnsp_size;
4834984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4835984c4197SStefano Zampini 
4836674ae819SStefano Zampini     /*
4837674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
48389162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
48399162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
48409162d606SStefano Zampini          There can be multiple constraints per connected component
4841674ae819SStefano Zampini                                                                                                                                                            */
4842674ae819SStefano Zampini     n_vertices = 0;
4843674ae819SStefano Zampini     if (ISForVertices) {
4844674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4845674ae819SStefano Zampini     }
48469162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
48479162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
48489162d606SStefano Zampini 
48499162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
48509162d606SStefano Zampini     total_counts *= max_constraints;
4851674ae819SStefano Zampini     total_counts += n_vertices;
48524641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
48539162d606SStefano Zampini 
4854674ae819SStefano Zampini     total_counts = 0;
4855674ae819SStefano Zampini     max_size_of_constraint = 0;
4856674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
48579162d606SStefano Zampini       IS used_is;
4858674ae819SStefano Zampini       if (i<n_ISForEdges) {
48599162d606SStefano Zampini         used_is = ISForEdges[i];
4860674ae819SStefano Zampini       } else {
48619162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4862674ae819SStefano Zampini       }
48639162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4864674ae819SStefano Zampini       total_counts += j;
4865674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4866674ae819SStefano Zampini     }
48679162d606SStefano 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);
48689162d606SStefano Zampini 
4869984c4197SStefano Zampini     /* get local part of global near null space vectors */
4870785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4871984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4872984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4873e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4874e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4875984c4197SStefano Zampini     }
4876674ae819SStefano Zampini 
4877242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4878242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4879a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4880242a89d7SStefano Zampini 
4881984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4882a773dcb8SStefano Zampini     if (!skip_lapack) {
4883674ae819SStefano Zampini       PetscScalar temp_work;
4884911cabfeSStefano Zampini 
4885674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4886984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4887785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4888785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4889785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4890674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4891785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4892674ae819SStefano Zampini #endif
4893674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4894c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4895c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4896674ae819SStefano Zampini       lwork = -1;
4897674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4898674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4899c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4900674ae819SStefano Zampini #else
4901c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4902674ae819SStefano Zampini #endif
4903674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4904984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4905674ae819SStefano Zampini #else /* on missing GESVD */
4906674ae819SStefano Zampini       /* SVD */
4907674ae819SStefano Zampini       PetscInt max_n,min_n;
4908674ae819SStefano Zampini       max_n = max_size_of_constraint;
4909984c4197SStefano Zampini       min_n = max_constraints;
4910984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4911674ae819SStefano Zampini         min_n = max_size_of_constraint;
4912984c4197SStefano Zampini         max_n = max_constraints;
4913674ae819SStefano Zampini       }
4914785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4915674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4916785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4917674ae819SStefano Zampini #endif
4918674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4919674ae819SStefano Zampini       lwork = -1;
4920e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4921e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4922b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4923674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4924674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
49259162d606SStefano 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));
4926674ae819SStefano Zampini #else
49279162d606SStefano 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));
4928674ae819SStefano Zampini #endif
4929674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4930984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4931984c4197SStefano Zampini #endif /* on missing GESVD */
4932674ae819SStefano Zampini       /* Allocate optimal workspace */
4933674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4934854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4935674ae819SStefano Zampini     }
4936674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4937674ae819SStefano Zampini     total_counts = 0;
49389162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
49399162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4940674ae819SStefano Zampini     /* vertices */
49419162d606SStefano Zampini     if (n_vertices) {
4942674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
49439162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4944674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
49459162d606SStefano Zampini         constraints_n[total_counts] = 1;
49469162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
49479162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
49489162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4949674ae819SStefano Zampini         total_counts++;
4950674ae819SStefano Zampini       }
4951674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4952674ae819SStefano Zampini       n_vertices = total_counts;
4953674ae819SStefano Zampini     }
4954984c4197SStefano Zampini 
4955674ae819SStefano Zampini     /* edges and faces */
49569162d606SStefano Zampini     total_counts_cc = total_counts;
4957911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
49589162d606SStefano Zampini       IS        used_is;
49599162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
49609162d606SStefano Zampini 
4961911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
49629162d606SStefano Zampini         used_is = ISForEdges[ncc];
4963984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4964674ae819SStefano Zampini       } else {
49659162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4966984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4967674ae819SStefano Zampini       }
4968674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
49699162d606SStefano Zampini 
49709162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
49719162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4972984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4973984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4974674ae819SStefano Zampini       if (nnsp_has_cnst) {
49755b08dc53SStefano Zampini         PetscScalar quad_value;
49769162d606SStefano Zampini 
49779162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
49789162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
49799162d606SStefano Zampini 
4980a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4981674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4982a773dcb8SStefano Zampini         } else {
4983a773dcb8SStefano Zampini           quad_value = 1.0;
4984a773dcb8SStefano Zampini         }
4985674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49869162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4987674ae819SStefano Zampini         }
49889162d606SStefano Zampini         temp_constraints++;
4989674ae819SStefano Zampini         total_counts++;
4990674ae819SStefano Zampini       }
4991674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4992984c4197SStefano Zampini         PetscReal real_value;
49939162d606SStefano Zampini         PetscScalar *ptr_to_data;
49949162d606SStefano Zampini 
4995984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
49969162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4997674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49989162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4999674ae819SStefano Zampini         }
5000984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
5001984c4197SStefano Zampini         /* check if array is null on the connected component */
5002e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
50039162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
50045b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5005674ae819SStefano Zampini           temp_constraints++;
5006674ae819SStefano Zampini           total_counts++;
50079162d606SStefano Zampini           if (!idxs_copied) {
50089162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
50099162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5010674ae819SStefano Zampini           }
5011674ae819SStefano Zampini         }
50129162d606SStefano Zampini       }
50139162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
501445a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5015eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5016a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
50179162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
50189162d606SStefano Zampini 
50199162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5020a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
50219162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5022a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
50239162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5024a773dcb8SStefano Zampini         } else { /* perform SVD */
5025984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
50269162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5027674ae819SStefano Zampini 
5028674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5029984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5030984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5031984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5032984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5033984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5034984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5035984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5036984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5037674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5038e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5039984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5040674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5041674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
50429162d606SStefano 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));
5043674ae819SStefano Zampini             }
5044674ae819SStefano Zampini           }
5045e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5046e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5047e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5048674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5049c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5050674ae819SStefano Zampini #else
5051c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5052674ae819SStefano Zampini #endif
5053674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5054984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5055984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5056674ae819SStefano Zampini           j = 0;
5057984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5058674ae819SStefano Zampini           total_counts = total_counts-j;
505945a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5060e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5061c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5062c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5063c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5064c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5065c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5066c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5067674ae819SStefano Zampini           if (j<temp_constraints) {
5068984c4197SStefano Zampini             PetscInt ii;
5069984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5070674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50719162d606SStefano 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));
5072674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5073984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5074674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
50759162d606SStefano 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];
5076674ae819SStefano Zampini               }
5077674ae819SStefano Zampini             }
5078674ae819SStefano Zampini           }
5079674ae819SStefano Zampini #else  /* on missing GESVD */
5080e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5081e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5082b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5083674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5084674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
50859162d606SStefano 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));
5086674ae819SStefano Zampini #else
50879162d606SStefano 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));
5088674ae819SStefano Zampini #endif
5089984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5090674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5091984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5092e310c8b4SStefano Zampini           k = temp_constraints;
5093e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5094674ae819SStefano Zampini           j = 0;
5095e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
509645a1bb75SStefano Zampini           valid_constraints = k-j;
5097911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5098984c4197SStefano Zampini #endif /* on missing GESVD */
5099674ae819SStefano Zampini         }
5100a773dcb8SStefano Zampini       }
51019162d606SStefano Zampini       /* update pointers information */
51029162d606SStefano Zampini       if (valid_constraints) {
51039162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
51049162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
51059162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
51069162d606SStefano Zampini         /* set change_of_basis flag */
510745a1bb75SStefano Zampini         if (boolforchange) {
5108b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
51099162d606SStefano Zampini         }
5110b3d85658SStefano Zampini         total_counts_cc++;
511145a1bb75SStefano Zampini       }
511245a1bb75SStefano Zampini     }
5113984c4197SStefano Zampini     /* free workspace */
51148f1c130eSStefano Zampini     if (!skip_lapack) {
5115984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5116984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5117984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5118984c4197SStefano Zampini #endif
5119984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5120984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5121984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5122984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5123984c4197SStefano Zampini #endif
5124984c4197SStefano Zampini     }
5125984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5126984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5127984c4197SStefano Zampini     }
5128984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5129cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5130cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5131cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5132cf5a6209SStefano Zampini     }
5133cf5a6209SStefano Zampini     if (n_ISForFaces) {
5134cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5135cf5a6209SStefano Zampini     }
5136cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5137cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5138cf5a6209SStefano Zampini     }
5139cf5a6209SStefano Zampini     if (n_ISForEdges) {
5140cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5141cf5a6209SStefano Zampini     }
5142cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
514308122e43SStefano Zampini   } else {
514408122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5145984c4197SStefano Zampini 
514608122e43SStefano Zampini     total_counts = 0;
514708122e43SStefano Zampini     n_vertices = 0;
5148d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5149d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
515008122e43SStefano Zampini     }
515108122e43SStefano Zampini     max_constraints = 0;
51529162d606SStefano Zampini     total_counts_cc = 0;
515308122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
515408122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
51559162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
515608122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
515708122e43SStefano Zampini     }
51589162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
51599162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
51609162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
51619162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
516274d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
51639162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
51649162d606SStefano Zampini     total_counts_cc = 0;
51659162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
51669162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
51679162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
516808122e43SStefano Zampini       }
516908122e43SStefano Zampini     }
51709162d606SStefano Zampini #if 0
51719162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
51729162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
51739162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
51749162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
51759162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
51769162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
51779162d606SStefano Zampini       }
51789162d606SStefano Zampini       printf("\n");
51799162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
51809162d606SStefano Zampini     }
51811b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
51828bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
51831b968477SStefano Zampini     }
51841b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
51858bec7fa6SStefano 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]);
51861b968477SStefano Zampini     }
518708122e43SStefano Zampini #endif
518808122e43SStefano Zampini 
51898bec7fa6SStefano Zampini     max_size_of_constraint = 0;
51909162d606SStefano 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]);
51919162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
519208122e43SStefano Zampini     /* Change of basis */
5193b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
519408122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
519508122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
519608122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5197b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
519808122e43SStefano Zampini         }
519908122e43SStefano Zampini       }
520008122e43SStefano Zampini     }
520108122e43SStefano Zampini   }
5202984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
52034f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
520408122e43SStefano Zampini 
52059162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
52069162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
52076c4ed002SBarry Smith   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
5208674ae819SStefano Zampini 
5209674ae819SStefano Zampini   /* Create constraint matrix */
5210674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
521116f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5212984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5213984c4197SStefano Zampini 
5214984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5215a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5216a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
521774d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5218984c4197SStefano Zampini   total_primal_vertices=0;
5219b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
52209162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
52219162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
522272b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
52239162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5224b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
522564efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
52269162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52279162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5228a717540cSStefano Zampini       }
5229b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
523091af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5231a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5232a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5233a717540cSStefano Zampini       }
5234fa434743SStefano Zampini     } else {
5235b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5236fa434743SStefano Zampini     }
5237a717540cSStefano Zampini   }
5238b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5239b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5240674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
524170022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5242b3d85658SStefano Zampini 
52434f1b2e48SStefano 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);
52440e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
52450e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5246984c4197SStefano Zampini 
5247984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
524874d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5249785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5250984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
525174d5cdf7SStefano Zampini 
5252984c4197SStefano Zampini   j = total_primal_vertices;
525374d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5254b3d85658SStefano Zampini   cum = total_primal_vertices;
52559162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52564641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5257b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5258b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5259b3d85658SStefano Zampini       cum++;
52609162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
526174d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
526274d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
526374d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
526474d5cdf7SStefano Zampini       }
52659162d606SStefano Zampini       j += constraints_n[i];
5266674ae819SStefano Zampini     }
5267674ae819SStefano Zampini   }
5268674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5269674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5270088faed8SStefano Zampini 
5271674ae819SStefano Zampini   /* set values in constraint matrix */
5272984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
52730e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5274674ae819SStefano Zampini   }
5275984c4197SStefano Zampini   total_counts = total_primal_vertices;
52769162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52774641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
52789162d606SStefano Zampini       PetscInt *cols;
52799162d606SStefano Zampini 
52809162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
52819162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
52829162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52839162d606SStefano Zampini         PetscInt    row = total_counts+k;
52849162d606SStefano Zampini         PetscScalar *vals;
52859162d606SStefano Zampini 
52869162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
52879162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
52889162d606SStefano Zampini       }
52899162d606SStefano Zampini       total_counts += constraints_n[i];
5290674ae819SStefano Zampini     }
5291674ae819SStefano Zampini   }
5292674ae819SStefano Zampini   /* assembling */
5293674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5294674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5295088faed8SStefano Zampini 
5296984c4197SStefano Zampini   /*
52976a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5298984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5299f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5300984c4197SStefano Zampini   */
5301674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5302674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5303026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5304984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5305984c4197SStefano Zampini     /* working stuff for GEQRF */
530681d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5307984c4197SStefano Zampini     PetscBLASInt lqr_work;
5308984c4197SStefano Zampini     /* working stuff for UNGQR */
5309984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5310984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5311984c4197SStefano Zampini     /* working stuff for TRTRS */
5312984c4197SStefano Zampini     PetscScalar  *trs_rhs;
53133f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5314984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5315984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5316984c4197SStefano Zampini     PetscScalar  *start_vals;
5317984c4197SStefano Zampini     /* working stuff for values insertion */
53184641a718SStefano Zampini     PetscBT      is_primal;
531964efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5320906d46d4SStefano Zampini     /* matrix sizes */
5321906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5322906d46d4SStefano Zampini     /* temporary change of basis */
5323906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5324cf5a6209SStefano Zampini     /* extra space for debugging */
5325cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5326984c4197SStefano Zampini 
5327906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5328906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
532916f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5330bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5331906d46d4SStefano Zampini     /* nonzeros for local mat */
5332bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
53331dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5334bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
53351dd7afcfSStefano Zampini     } else {
53361dd7afcfSStefano Zampini       const PetscInt *ii;
53371dd7afcfSStefano Zampini       PetscInt       n;
53381dd7afcfSStefano Zampini       PetscBool      flg_row;
53391dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53401dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
53411dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53421dd7afcfSStefano Zampini     }
53439162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5344a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
53459162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5346a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
53479162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5348a717540cSStefano Zampini         } else {
53499162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
53509162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5351a717540cSStefano Zampini         }
5352a717540cSStefano Zampini       }
5353a717540cSStefano Zampini     }
5354906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5355bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
53561dd7afcfSStefano Zampini     /* Set interior change in the matrix */
53571dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5358bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5359906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5360a717540cSStefano Zampini       }
53611dd7afcfSStefano Zampini     } else {
53621dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
53631dd7afcfSStefano Zampini       PetscScalar    *aa;
53641dd7afcfSStefano Zampini       PetscInt       n;
53651dd7afcfSStefano Zampini       PetscBool      flg_row;
53661dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53671dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53681dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
53691dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
53701dd7afcfSStefano Zampini       }
53711dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53721dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53731dd7afcfSStefano Zampini     }
5374a717540cSStefano Zampini 
5375a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5376a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5377a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5378a717540cSStefano Zampini     }
5379a717540cSStefano Zampini 
5380a717540cSStefano Zampini 
5381a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5382a717540cSStefano Zampini     /*
5383a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5384a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5385a717540cSStefano Zampini 
5386a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5387a717540cSStefano Zampini 
5388a6b551f4SStefano 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)
5389a6b551f4SStefano Zampini 
5390a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5391a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5392a717540cSStefano Zampini             |              ...                        |
5393a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5394a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5395a717540cSStefano Zampini 
5396a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5397a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5398a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5399a6b551f4SStefano Zampini 
5400a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5401a717540cSStefano Zampini     */
5402a717540cSStefano Zampini     if (qr_needed) {
5403984c4197SStefano Zampini       /* space to store Q */
5404854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
54054e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
54064e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5407984c4197SStefano Zampini       /* first we issue queries for optimal work */
54083f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
54103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5411984c4197SStefano Zampini       lqr_work = -1;
54123f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5413984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5414984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5415785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5416984c4197SStefano Zampini       lgqr_work = -1;
54173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54183f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
54193f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
54203f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54213f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
54223f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5423984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5424984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5425785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5426984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5427785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5428a717540cSStefano Zampini       /* allocating workspace for check */
5429a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5430cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5431a717540cSStefano Zampini       }
5432a717540cSStefano Zampini     }
5433984c4197SStefano Zampini     /* array to store whether a node is primal or not */
54344641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5435473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
54360e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
54376c4ed002SBarry Smith     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
543839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
543939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
544039e2fb2aSStefano Zampini     }
544139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5442984c4197SStefano Zampini 
5443a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
54449162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
54459162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
54464641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5447984c4197SStefano Zampini         /* get constraint info */
54489162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5449984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5450984c4197SStefano Zampini 
5451984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
54529162d606SStefano 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);
5453674ae819SStefano Zampini         }
5454984c4197SStefano Zampini 
5455fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5456a717540cSStefano Zampini 
5457a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5458a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
54599162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5460a717540cSStefano Zampini           }
5461984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
54629162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5463984c4197SStefano Zampini 
5464984c4197SStefano Zampini           /* compute QR decomposition of constraints */
54653f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54663f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54673f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5468674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54693f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5470984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5471674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5472984c4197SStefano Zampini 
5473984c4197SStefano Zampini           /* explictly compute R^-T */
5474984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5475984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
54763f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54773f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
54783f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54793f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5480984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54813f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5482984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5483984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5484984c4197SStefano Zampini 
5485a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
54863f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54873f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54883f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54893f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5490984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54913f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5492984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5493984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5494984c4197SStefano Zampini 
5495984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5496984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5497984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
54983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54993f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
55003f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
55013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
55023f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
55033f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5504984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
55059162d606SStefano 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));
5506984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
55079162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5508984c4197SStefano Zampini 
5509984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
55109162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5511984c4197SStefano Zampini           /* insert cols for primal dofs */
5512984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5513984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
55149162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5515906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5516984c4197SStefano Zampini           }
5517984c4197SStefano Zampini           /* insert cols for dual dofs */
5518984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
55199162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5520984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
55219162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5522906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5523984c4197SStefano Zampini               j++;
5524674ae819SStefano Zampini             }
5525674ae819SStefano Zampini           }
5526984c4197SStefano Zampini 
5527984c4197SStefano Zampini           /* check change of basis */
5528984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5529984c4197SStefano Zampini             PetscInt   ii,jj;
5530984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5531c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5532c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5533c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5534c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5535c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5536c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5537984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5538cf5a6209SStefano 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));
5539984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5540984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5541984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5542cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5543cf5a6209SStefano 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;
5544674ae819SStefano Zampini               }
5545674ae819SStefano Zampini             }
5546984c4197SStefano Zampini             if (!valid_qr) {
554722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5548984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5549984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5550cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5551cf5a6209SStefano 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]));
5552674ae819SStefano Zampini                   }
5553cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5554cf5a6209SStefano 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]));
5555984c4197SStefano Zampini                   }
5556984c4197SStefano Zampini                 }
5557984c4197SStefano Zampini               }
5558674ae819SStefano Zampini             } else {
555922d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5560674ae819SStefano Zampini             }
5561674ae819SStefano Zampini           }
5562a717540cSStefano Zampini         } else { /* simple transformation block */
5563a717540cSStefano Zampini           PetscInt    row,col;
5564a6b551f4SStefano Zampini           PetscScalar val,norm;
5565a6b551f4SStefano Zampini 
5566a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55679162d606SStefano 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));
5568a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
55699162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
55709162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5571bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
55729162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5573906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
55749162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5575a717540cSStefano Zampini             } else {
5576a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
55779162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5578a717540cSStefano Zampini                 if (row != col) {
55799162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5580a717540cSStefano Zampini                 } else {
55819162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5582a717540cSStefano Zampini                 }
5583906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5584a717540cSStefano Zampini               }
5585a717540cSStefano Zampini             }
5586a717540cSStefano Zampini           }
558798a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
558822d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5589a717540cSStefano Zampini           }
5590674ae819SStefano Zampini         }
5591984c4197SStefano Zampini       } else {
5592984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
55939162d606SStefano 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);
5594674ae819SStefano Zampini         }
5595674ae819SStefano Zampini       }
5596674ae819SStefano Zampini     }
5597a717540cSStefano Zampini 
5598a717540cSStefano Zampini     /* free workspace */
5599a717540cSStefano Zampini     if (qr_needed) {
5600984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5601cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5602984c4197SStefano Zampini       }
5603984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5604984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5605984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5606984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5607984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5608674ae819SStefano Zampini     }
5609a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5610906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5611906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5612906d46d4SStefano Zampini 
5613906d46d4SStefano Zampini     /* assembling of global change of variable */
561488c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5615bbb9e6c6SStefano Zampini       Mat      tmat;
561616f15bc4SStefano Zampini       PetscInt bs;
561716f15bc4SStefano Zampini 
5618906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5619906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5620bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5621bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5622bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5623bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
562416f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
562516f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5626906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5627bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5628bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5629bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5630bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5631bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5632e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5633e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5634bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5635bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
563688c03ad3SStefano Zampini 
5637906d46d4SStefano Zampini       /* check */
5638906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5639906d46d4SStefano Zampini         PetscReal error;
5640906d46d4SStefano Zampini         Vec       x,x_change;
5641906d46d4SStefano Zampini 
5642906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5643906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5644906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5645906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5646e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5647e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5648bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5649e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5650e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5651906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5652906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5653906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5654906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5655bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5656906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5657906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5658906d46d4SStefano Zampini       }
5659b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5660b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5661b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5662bf3a8328SStefano Zampini 
56639a962809SStefano 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);
5664b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5665ac632422SStefano Zampini           Mat                    S_new,tmat;
5666bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5667bbb9e6c6SStefano Zampini 
5668bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
56696816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5670bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5671bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5672bf3a8328SStefano Zampini             IS                     is_V;
5673b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5674b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5675b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5676b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5677b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5678bf3a8328SStefano Zampini           }
5679bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5680ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5681b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5682ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5683bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5684bf3a8328SStefano Zampini             const PetscScalar *array;
5685bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5686bf3a8328SStefano Zampini             PetscInt          i,n_V;
5687bf3a8328SStefano Zampini 
5688b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5689b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5690b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5691b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5692b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5693b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5694b087196eSStefano Zampini               PetscScalar val;
5695b087196eSStefano Zampini               PetscInt    idx;
5696b087196eSStefano Zampini 
5697b087196eSStefano Zampini               idx = idxs_V[i];
5698b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5699b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5700b087196eSStefano Zampini             }
5701b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5702b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5703bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5704bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5705bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5706bf3a8328SStefano Zampini           }
5707ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5708ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5709ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5710ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5711b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5712ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5713bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5714b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5715bf3a8328SStefano Zampini             }
5716ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5717ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5718ac632422SStefano Zampini           }
5719b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
572088c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5721b96c3477SStefano Zampini         }
5722c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5723b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5724c9db6a07SStefano Zampini           PetscInt i;
5725c9db6a07SStefano Zampini 
5726c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5727c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5728c9db6a07SStefano Zampini           }
5729c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5730c9db6a07SStefano Zampini         }
5731b96c3477SStefano Zampini       }
573216909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
573316909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
573416909a7fSStefano Zampini       } else {
5735906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
573616909a7fSStefano Zampini       }
57371dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
573827b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
573972b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
574072b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
574172b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
574272b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
574372b8c272SStefano Zampini     }
57441dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
574527b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5746b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5747b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5748906d46d4SStefano Zampini     } else {
57491dd7afcfSStefano Zampini       Mat benign_global = NULL;
575027b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
57511dd7afcfSStefano Zampini         Mat tmat;
57521dd7afcfSStefano Zampini 
57531dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
57541dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
57551dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
57561dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57571dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57581dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
57591dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57601dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57611dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
57621dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
57631dd7afcfSStefano Zampini           Mat M;
57641dd7afcfSStefano Zampini 
57651dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
57661dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
57671dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
57681dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5769906d46d4SStefano Zampini         } else {
57701dd7afcfSStefano Zampini           Mat         eye;
57711dd7afcfSStefano Zampini           PetscScalar *array;
57721dd7afcfSStefano Zampini 
57731dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57741dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
57751dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
57761dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5777906d46d4SStefano Zampini           }
57781dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57791dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57801dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57811dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
57821dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
57831dd7afcfSStefano Zampini         }
57841dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
57851dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
57861dd7afcfSStefano Zampini       }
57871dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
57881dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57891dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
579027b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
57911dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
57921dd7afcfSStefano Zampini       }
57931dd7afcfSStefano Zampini     }
579416909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
579516909a7fSStefano Zampini       IS             is_global;
579616909a7fSStefano Zampini       const PetscInt *gidxs;
579716909a7fSStefano Zampini 
579816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
579916909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
580016909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
580116909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
580216909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
580316909a7fSStefano Zampini     }
58041dd7afcfSStefano Zampini   }
58051dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
58061dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5807b9b85e73SStefano Zampini   }
5808a717540cSStefano Zampini 
580972b8c272SStefano Zampini   if (!pcbddc->fake_change) {
58104f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
58114f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58124f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
58134f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5814019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5815019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5816019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5817019a44ceSStefano Zampini     }
5818019a44ceSStefano Zampini 
5819019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5820727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5821727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
58229f47a83aSStefano 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);
5823c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
58240e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
58259f47a83aSStefano 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);
5826727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5827727cdba6SStefano Zampini       }
58280e6343abSStefano Zampini     }
5829727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5830b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
583172b8c272SStefano Zampini   }
583272b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5833727cdba6SStefano Zampini 
5834a717540cSStefano Zampini   /* flush dbg viewer */
5835b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5836b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5837b8ffe317SStefano Zampini   }
5838a717540cSStefano Zampini 
5839e310c8b4SStefano Zampini   /* free workspace */
5840a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
58414641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
584208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
58439162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
58449162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
584508122e43SStefano Zampini   } else {
58469162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
58479162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
58489162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
584908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
585008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
58519162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
58529162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
585308122e43SStefano Zampini   }
5854674ae819SStefano Zampini   PetscFunctionReturn(0);
5855674ae819SStefano Zampini }
5856674ae819SStefano Zampini 
5857674ae819SStefano Zampini #undef __FUNCT__
5858674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5859674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5860674ae819SStefano Zampini {
586171582508SStefano Zampini   ISLocalToGlobalMapping map;
5862674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5863674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
586414f95afaSStefano Zampini   PetscInt               ierr,i,N;
5865674ae819SStefano Zampini 
5866674ae819SStefano Zampini   PetscFunctionBegin;
5867*8af8fcf9SStefano Zampini   if (pcbddc->recompute_topography) {
58688e61c736SStefano Zampini     /* Reset previously computed graph */
58698e61c736SStefano Zampini     ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5870674ae819SStefano Zampini     /* Init local Graph struct */
58717fb0e2dbSStefano Zampini     ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
587271582508SStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5873be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5874674ae819SStefano Zampini 
5875575ad6abSStefano Zampini     /* Check validity of the csr graph passed in by the user */
58769a962809SStefano 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);
58779577ea80SStefano Zampini 
5878674ae819SStefano Zampini     /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5879d4d8cf7bSStefano Zampini     if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
58804d379d7bSStefano Zampini       PetscInt  *xadj,*adjncy;
58814d379d7bSStefano Zampini       PetscInt  nvtxs;
5882e496cd5dSStefano Zampini       PetscBool flg_row=PETSC_FALSE;
5883674ae819SStefano Zampini 
58842fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
58852fffb893SStefano Zampini       if (flg_row) {
58864d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5887b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
58882fffb893SStefano Zampini       }
58892fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5890674ae819SStefano Zampini     }
58919b28b941SStefano Zampini     if (pcbddc->dbg_flag) {
58929b28b941SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5893674ae819SStefano Zampini     }
5894674ae819SStefano Zampini 
5895674ae819SStefano Zampini     /* Setup of Graph */
58964b2aedd3SStefano Zampini     pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
589714f95afaSStefano 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);
5898674ae819SStefano Zampini 
58994f1b2e48SStefano Zampini     /* attach info on disconnected subdomains if present */
59004f1b2e48SStefano Zampini     if (pcbddc->n_local_subs) {
59014f1b2e48SStefano Zampini       PetscInt *local_subs;
59024f1b2e48SStefano Zampini 
59034f1b2e48SStefano Zampini       ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
59044f1b2e48SStefano Zampini       for (i=0;i<pcbddc->n_local_subs;i++) {
59054f1b2e48SStefano Zampini         const PetscInt *idxs;
59064f1b2e48SStefano Zampini         PetscInt       nl,j;
59074f1b2e48SStefano Zampini 
59084f1b2e48SStefano Zampini         ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
59094f1b2e48SStefano Zampini         ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
591071582508SStefano Zampini         for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
59114f1b2e48SStefano Zampini         ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
59124f1b2e48SStefano Zampini       }
59134f1b2e48SStefano Zampini       pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
59144f1b2e48SStefano Zampini       pcbddc->mat_graph->local_subs = local_subs;
59154f1b2e48SStefano Zampini     }
5916*8af8fcf9SStefano Zampini     pcbddc->graphanalyzed = PETSC_FALSE;
5917*8af8fcf9SStefano Zampini   }
59184f1b2e48SStefano Zampini 
5919*8af8fcf9SStefano Zampini   if (pcbddc->graphanalyzed) {
5920674ae819SStefano Zampini     /* Graph's connected components analysis */
5921674ae819SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
592271582508SStefano Zampini     pcbddc->graphanalyzed = PETSC_TRUE;
5923*8af8fcf9SStefano Zampini   }
5924674ae819SStefano Zampini   PetscFunctionReturn(0);
5925674ae819SStefano Zampini }
5926674ae819SStefano Zampini 
59279a7d3425SStefano Zampini #undef __FUNCT__
59289a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
59299a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
59309a7d3425SStefano Zampini {
59319a7d3425SStefano Zampini   PetscInt       i,j;
59329a7d3425SStefano Zampini   PetscScalar    *alphas;
59339a7d3425SStefano Zampini   PetscErrorCode ierr;
59349a7d3425SStefano Zampini 
59359a7d3425SStefano Zampini   PetscFunctionBegin;
5936785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
59379a7d3425SStefano Zampini   for (i=0;i<n;i++) {
59389a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5939669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5940669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5941669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
59429a7d3425SStefano Zampini   }
59439a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
59449a7d3425SStefano Zampini   PetscFunctionReturn(0);
59459a7d3425SStefano Zampini }
59469a7d3425SStefano Zampini 
5947e7931f94SStefano Zampini #undef __FUNCT__
594870cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
594957de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5950e7931f94SStefano Zampini {
595157de7509SStefano Zampini   Mat            A;
5952e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5953e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
595452e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
595552e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
595627b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
595757de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
595827b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
595927b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
596027b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
596127b6a85dSStefano Zampini   MPI_Comm       subcomm;
596252e5ac9dSStefano Zampini   PetscErrorCode ierr;
5963a57a6d2fSStefano Zampini 
5964e7931f94SStefano Zampini   PetscFunctionBegin;
596557de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
596657de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
596757de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
596857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
596957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
597057de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
597157de7509SStefano Zampini 
597257de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
597357de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
597457de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
597557de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
597657de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
597757de7509SStefano Zampini   im_active = !!(n);
597857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
597957de7509SStefano Zampini   void_procs = size - active_procs;
598057de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
598157de7509SStefano Zampini   if (void_procs) {
598257de7509SStefano Zampini     PetscInt ncand;
598357de7509SStefano Zampini 
598457de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
598557de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
598657de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
598757de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
598857de7509SStefano Zampini       if (!procs_candidates[i]) {
598957de7509SStefano Zampini         procs_candidates[ncand++] = i;
599057de7509SStefano Zampini       }
599157de7509SStefano Zampini     }
599257de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
599357de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
599457de7509SStefano Zampini   }
599557de7509SStefano Zampini 
599614f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
599714f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
599814f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
599914f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
600014f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
600114f0bfb9SStefano Zampini     else dest = rank;
600257de7509SStefano Zampini     if (im_active) {
600357de7509SStefano Zampini       issize = 1;
600457de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
600514f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
600657de7509SStefano Zampini       } else {
600714f0bfb9SStefano Zampini         isidx = dest;
600857de7509SStefano Zampini       }
600957de7509SStefano Zampini     } else {
601057de7509SStefano Zampini       issize = 0;
601157de7509SStefano Zampini       isidx = -1;
601257de7509SStefano Zampini     }
601357de7509SStefano Zampini     *n_subdomains = active_procs;
601457de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6015daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
601657de7509SStefano Zampini     PetscFunctionReturn(0);
601757de7509SStefano Zampini   }
6018c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6019c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
602027b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6021e7931f94SStefano Zampini 
6022e7931f94SStefano Zampini   /* Get info on mapping */
60233bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
60243bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6025e7931f94SStefano Zampini 
6026e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6027785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6028e7931f94SStefano Zampini   xadj[0] = 0;
6029e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6030785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6031785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
603227b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
603327b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
603427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
603527b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6036e7931f94SStefano Zampini 
603727b6a85dSStefano Zampini   xadj_count = 0;
60382b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
603927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
604027b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6041d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6042d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6043d023bfaeSStefano Zampini         xadj_count++;
604427b6a85dSStefano Zampini         break;
604527b6a85dSStefano Zampini       }
6046e7931f94SStefano Zampini     }
6047e7931f94SStefano Zampini   }
6048d023bfaeSStefano Zampini   xadj[1] = xadj_count;
604927b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
60503bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6051e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6052e7931f94SStefano Zampini 
60533837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6054e7931f94SStefano Zampini 
605527b6a85dSStefano Zampini   /* Restrict work on active processes only */
605627b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
605727b6a85dSStefano Zampini   if (void_procs) {
605827b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
605927b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
606027b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
606127b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
606227b6a85dSStefano Zampini   } else {
606327b6a85dSStefano Zampini     psubcomm = NULL;
606427b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
606527b6a85dSStefano Zampini   }
606627b6a85dSStefano Zampini 
606727b6a85dSStefano Zampini   v_wgt = NULL;
606827b6a85dSStefano Zampini   if (!color) {
6069e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6070e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6071e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6072c8587f34SStefano Zampini   } else {
607352e5ac9dSStefano Zampini     Mat             subdomain_adj;
607452e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
607552e5ac9dSStefano Zampini     MatPartitioning partitioner;
607627b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
607752e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
607857de7509SStefano Zampini     PetscMPIInt     size;
6079b0c7d250SStefano Zampini     PetscBool       aggregate;
6080b0c7d250SStefano Zampini 
608127b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
608227b6a85dSStefano Zampini     if (void_procs) {
608327b6a85dSStefano Zampini       PetscInt prank = rank;
6084785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
608527b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6086e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6087e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6088c8587f34SStefano Zampini       }
6089e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
609027b6a85dSStefano Zampini     } else {
609127b6a85dSStefano Zampini       oldranks = NULL;
609227b6a85dSStefano Zampini     }
6093b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
609427b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6095b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6096b0c7d250SStefano Zampini       PetscMPIInt nrank;
6097b0c7d250SStefano Zampini       PetscScalar *vals;
6098b0c7d250SStefano Zampini 
609927b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6100b0c7d250SStefano Zampini       lrows = 0;
6101b0c7d250SStefano Zampini       if (nrank<redprocs) {
6102b0c7d250SStefano Zampini         lrows = size/redprocs;
6103b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6104b0c7d250SStefano Zampini       }
610527b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6106b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6107b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6108b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6109b0c7d250SStefano Zampini       row = nrank;
6110b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6111b0c7d250SStefano Zampini       cols = adjncy;
6112b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6113b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6114b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6115b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6116b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
611752e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
611852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
611952e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6120b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
612127b6a85dSStefano Zampini       if (use_vwgt) {
612227b6a85dSStefano Zampini         Vec               v;
612327b6a85dSStefano Zampini         const PetscScalar *array;
612427b6a85dSStefano Zampini         PetscInt          nl;
612527b6a85dSStefano Zampini 
612627b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
612727b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
612827b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
612927b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
613027b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
613127b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
613227b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
613322db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
613427b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
613527b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
613627b6a85dSStefano Zampini       }
6137b0c7d250SStefano Zampini     } else {
613827b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
613927b6a85dSStefano Zampini       if (use_vwgt) {
614027b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
614127b6a85dSStefano Zampini         v_wgt[0] = local_size;
614227b6a85dSStefano Zampini       }
6143b0c7d250SStefano Zampini     }
614422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6145e7931f94SStefano Zampini 
6146e7931f94SStefano Zampini     /* Partition */
614727b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6148e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
614927b6a85dSStefano Zampini     if (v_wgt) {
6150e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6151c8587f34SStefano Zampini     }
615257de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
615357de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6154e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6155e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
615622b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6157e7931f94SStefano Zampini 
615852e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
61596583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
616052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
616152e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
616257de7509SStefano Zampini     if (!aggregate) {
616357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
616427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
616527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
616627b6a85dSStefano Zampini #endif
616757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
616827b6a85dSStefano Zampini       } else if (oldranks) {
6169b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
617027b6a85dSStefano Zampini       } else {
617127b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
617257de7509SStefano Zampini       }
617328143c3dSStefano Zampini     } else {
6174b0c7d250SStefano Zampini       PetscInt    idxs[1];
6175b0c7d250SStefano Zampini       PetscMPIInt tag;
6176b0c7d250SStefano Zampini       MPI_Request *reqs;
6177b0c7d250SStefano Zampini 
6178b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6179b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6180b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
618127b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
618228143c3dSStefano Zampini       }
618327b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6184b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6185b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
618657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
618727b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
618827b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
618927b6a85dSStefano Zampini #endif
619057de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
619127b6a85dSStefano Zampini       } else if (oldranks) {
6192b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
619327b6a85dSStefano Zampini       } else {
619427b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6195e7931f94SStefano Zampini       }
619657de7509SStefano Zampini     }
619752e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6198e7931f94SStefano Zampini     /* clean up */
6199e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
620052e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6201e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6202e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6203e7931f94SStefano Zampini   }
620427b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
620557de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6206e7931f94SStefano Zampini 
6207e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6208e7931f94SStefano Zampini   i = 1;
620927b6a85dSStefano Zampini   if (!color) i=0;
621057de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6211e7931f94SStefano Zampini   PetscFunctionReturn(0);
6212e7931f94SStefano Zampini }
6213e7931f94SStefano Zampini 
6214e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6215e7931f94SStefano Zampini 
6216e7931f94SStefano Zampini #undef __FUNCT__
6217e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
62181ae86dd6SStefano Zampini PetscErrorCode MatISSubassemble(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[])
6219e7931f94SStefano Zampini {
622070cf5478SStefano Zampini   Mat                    local_mat;
6221e7931f94SStefano Zampini   IS                     is_sends_internal;
62229d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
62231ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
62249d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6225e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6226e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6227e7931f94SStefano Zampini   const PetscInt*        is_indices;
6228e7931f94SStefano Zampini   MatType                new_local_type;
6229e7931f94SStefano Zampini   /* buffers */
6230e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
623128143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
62329d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6233e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
62341ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6235e7931f94SStefano Zampini   /* MPI */
623628143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
623728143c3dSStefano Zampini   PetscSubcomm           subcomm;
6238e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
623928143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
624028143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
62411ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
62421ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
62431ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6244e7931f94SStefano Zampini   PetscErrorCode         ierr;
6245e7931f94SStefano Zampini 
6246e7931f94SStefano Zampini   PetscFunctionBegin;
624757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6248e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
624928143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
625057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
625157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
625257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
625357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
625457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
62551ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
62561ae86dd6SStefano Zampini   if (nvecs) {
62571ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
62581ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
62591ae86dd6SStefano Zampini   }
626057de7509SStefano Zampini   /* further checks */
6261e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6262e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6263e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6264e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6265e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
626657de7509SStefano Zampini   if (reuse && *mat_n) {
626770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
626857de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
626970cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
627028143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
627170cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
627270cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
627370cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
627470cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
627570cf5478SStefano Zampini   }
6276e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6277e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
627857de7509SStefano Zampini 
6279e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6280e7931f94SStefano Zampini   if (!is_sends) {
628128143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
628257de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6283c8587f34SStefano Zampini   } else {
6284e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6285e7931f94SStefano Zampini     is_sends_internal = is_sends;
6286c8587f34SStefano Zampini   }
6287e7931f94SStefano Zampini 
6288e7931f94SStefano Zampini   /* get comm */
6289a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6290e7931f94SStefano Zampini 
6291e7931f94SStefano Zampini   /* compute number of sends */
6292e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6293e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6294e7931f94SStefano Zampini 
6295e7931f94SStefano Zampini   /* compute number of receives */
6296e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6297785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6298e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6299e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6300e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6301e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6302e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6303e7931f94SStefano Zampini 
630428143c3dSStefano Zampini   /* restrict comm if requested */
630528143c3dSStefano Zampini   subcomm = 0;
630628143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
630728143c3dSStefano Zampini   if (restrict_comm) {
6308779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6309779c1cceSStefano Zampini 
631028143c3dSStefano Zampini     color = 0;
631153a05cb3SStefano Zampini     if (restrict_full) {
631253a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
631353a05cb3SStefano Zampini     } else {
631453a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
631553a05cb3SStefano Zampini     }
6316b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
631728143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
631828143c3dSStefano Zampini     /* check if reuse has been requested */
631957de7509SStefano Zampini     if (reuse) {
632028143c3dSStefano Zampini       if (*mat_n) {
632128143c3dSStefano Zampini         PetscMPIInt subcommsize2;
632228143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
632328143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
632428143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
632528143c3dSStefano Zampini       } else {
632628143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
632728143c3dSStefano Zampini       }
632828143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6329779c1cceSStefano Zampini       PetscMPIInt rank;
6330779c1cceSStefano Zampini 
6331779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
633228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
633328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
633428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6335306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
633628143c3dSStefano Zampini     }
633728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
633828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
633928143c3dSStefano Zampini   } else {
634028143c3dSStefano Zampini     comm_n = comm;
634128143c3dSStefano Zampini   }
634228143c3dSStefano Zampini 
6343e7931f94SStefano Zampini   /* prepare send/receive buffers */
6344785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6345e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6346785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6347e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
634828143c3dSStefano Zampini   if (nis) {
6349854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
635028143c3dSStefano Zampini   }
6351e7931f94SStefano Zampini 
635228143c3dSStefano Zampini   /* Get data from local matrices */
63536c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6354e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6355e7931f94SStefano Zampini     /*
6356e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6357e7931f94SStefano Zampini        send_buffer_idxs should contain:
6358e7931f94SStefano Zampini        - MatType_PRIVATE type
6359e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6360e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6361e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6362e7931f94SStefano Zampini     */
63636c4ed002SBarry Smith   else {
6364e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
63653bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6366854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6367e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6368e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
63693bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6370e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
63713bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6372e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6373e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6374e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6375e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6376c8587f34SStefano Zampini     }
6377c8587f34SStefano Zampini   }
6378e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
637928143c3dSStefano Zampini   /* additional is (if any) */
638028143c3dSStefano Zampini   if (nis) {
638128143c3dSStefano Zampini     PetscMPIInt psum;
638228143c3dSStefano Zampini     PetscInt j;
638328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
638428143c3dSStefano Zampini       PetscInt plen;
638528143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
638628143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
638728143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
638828143c3dSStefano Zampini     }
6389854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
639028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
639128143c3dSStefano Zampini       PetscInt plen;
639228143c3dSStefano Zampini       const PetscInt *is_array_idxs;
639328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
639428143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
639528143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
639628143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
639728143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
639828143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
639928143c3dSStefano Zampini     }
640028143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
640128143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
640228143c3dSStefano Zampini     }
640328143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
640428143c3dSStefano Zampini   }
640528143c3dSStefano Zampini 
6406e7931f94SStefano Zampini   buf_size_idxs = 0;
6407e7931f94SStefano Zampini   buf_size_vals = 0;
640828143c3dSStefano Zampini   buf_size_idxs_is = 0;
64091ae86dd6SStefano Zampini   buf_size_vecs = 0;
6410e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6411e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6412e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
641328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
64141ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6415e7931f94SStefano Zampini   }
6416785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6417785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
641895ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
64191ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6420e7931f94SStefano Zampini 
6421e7931f94SStefano Zampini   /* get new tags for clean communications */
6422e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6423e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
642428143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
64251ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6426e7931f94SStefano Zampini 
6427e7931f94SStefano Zampini   /* allocate for requests */
6428785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6429785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
643095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
64311ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6432785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6433785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
643495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
64351ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6436e7931f94SStefano Zampini 
6437e7931f94SStefano Zampini   /* communications */
6438e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6439e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
644028143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
64411ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6442e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6443e7931f94SStefano Zampini     source_dest = onodes[i];
6444e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6445e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6446e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6447e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
644828143c3dSStefano Zampini     if (nis) {
644957de7509SStefano Zampini       source_dest = onodes_is[i];
645028143c3dSStefano 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);
645128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
645228143c3dSStefano Zampini     }
64531ae86dd6SStefano Zampini     if (nvecs) {
64541ae86dd6SStefano Zampini       source_dest = onodes[i];
64551ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
64561ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
64571ae86dd6SStefano Zampini     }
6458e7931f94SStefano Zampini   }
6459e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6460e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6461e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6462e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
646328143c3dSStefano Zampini     if (nis) {
646428143c3dSStefano 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);
646528143c3dSStefano Zampini     }
64661ae86dd6SStefano Zampini     if (nvecs) {
64671ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64681ae86dd6SStefano 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);
64691ae86dd6SStefano Zampini     }
6470e7931f94SStefano Zampini   }
6471e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6472e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6473e7931f94SStefano Zampini 
6474e7931f94SStefano Zampini   /* assemble new l2g map */
6475e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6476e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64779d30be91SStefano Zampini   new_local_rows = 0;
6478e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64799d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6480e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6481e7931f94SStefano Zampini   }
64829d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6483e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64849d30be91SStefano Zampini   new_local_rows = 0;
6485e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64869d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
64879d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6488e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6489e7931f94SStefano Zampini   }
64909d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
64919d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6492e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6493e7931f94SStefano Zampini 
6494e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6495e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6496e7931f94SStefano 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) */
6497e7931f94SStefano Zampini   if (n_recvs) {
649828143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6499e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6500e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6501e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6502e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6503e7931f94SStefano Zampini         break;
6504e7931f94SStefano Zampini       }
6505e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6506e7931f94SStefano Zampini     }
6507e7931f94SStefano Zampini     switch (new_local_type_private) {
650828143c3dSStefano Zampini       case MATDENSE_PRIVATE:
650928143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6510e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6511e7931f94SStefano Zampini           bs = 1;
651228143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
651328143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
651428143c3dSStefano Zampini           bs = 1;
651528143c3dSStefano Zampini         }
6516e7931f94SStefano Zampini         break;
6517e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6518e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6519e7931f94SStefano Zampini         bs = 1;
6520e7931f94SStefano Zampini         break;
6521e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6522e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6523e7931f94SStefano Zampini         break;
6524e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6525e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6526e7931f94SStefano Zampini         break;
6527e7931f94SStefano Zampini       default:
65289d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6529e7931f94SStefano Zampini         break;
6530e7931f94SStefano Zampini     }
653128143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
653228143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
653328143c3dSStefano Zampini     bs = 1;
6534e7931f94SStefano Zampini   }
6535e7931f94SStefano Zampini 
653670cf5478SStefano Zampini   /* create MATIS object if needed */
653757de7509SStefano Zampini   if (!reuse) {
6538e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6539e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
654070cf5478SStefano Zampini   } else {
654170cf5478SStefano Zampini     /* it also destroys the local matrices */
654257de7509SStefano Zampini     if (*mat_n) {
654370cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
654457de7509SStefano Zampini     } else { /* this is a fake object */
654557de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
654657de7509SStefano Zampini     }
654770cf5478SStefano Zampini   }
654870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6549e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
65509d30be91SStefano Zampini 
65519d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
65529d30be91SStefano Zampini 
65539d30be91SStefano Zampini   /* Global to local map of received indices */
65549d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
65559d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
65569d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
65579d30be91SStefano Zampini 
65589d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
65599d30be91SStefano Zampini   buf_size_idxs = 0;
65609d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
65619d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
65629d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
65639d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
65649d30be91SStefano Zampini   }
65659d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
65669d30be91SStefano Zampini 
65679d30be91SStefano Zampini   /* set preallocation */
65689d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
65699d30be91SStefano Zampini   if (!newisdense) {
65709d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
65719d30be91SStefano Zampini 
65729d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
65739d30be91SStefano Zampini     if (n_recvs) {
65749d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
65759d30be91SStefano Zampini     }
65769d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
65779d30be91SStefano Zampini       PetscInt j;
65789d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
65799d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
65809d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
65819d30be91SStefano Zampini         }
65829d30be91SStefano Zampini       } else {
65839d30be91SStefano Zampini         /* TODO */
65849d30be91SStefano Zampini       }
65859d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
65869d30be91SStefano Zampini     }
65879d30be91SStefano Zampini     if (new_local_nnz) {
65889d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
65899d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
65909d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
65919d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65929d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
65939d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65949d30be91SStefano Zampini     } else {
65959d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65969d30be91SStefano Zampini     }
65979d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
65989d30be91SStefano Zampini   } else {
65999d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
66009d30be91SStefano Zampini   }
6601e7931f94SStefano Zampini 
6602e7931f94SStefano Zampini   /* set values */
6603e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
66049d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6605e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6606e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6607e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
66089d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6609e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6610e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6611e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
661228143c3dSStefano Zampini     } else {
661328143c3dSStefano Zampini       /* TODO */
6614e7931f94SStefano Zampini     }
6615e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6616e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6617e7931f94SStefano Zampini   }
6618e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6619e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
662070cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
662170cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66229d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6623e7931f94SStefano Zampini 
6624dfd14d43SStefano Zampini #if 0
662528143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6626e7931f94SStefano Zampini     Vec       lvec,rvec;
6627e7931f94SStefano Zampini     PetscReal infty_error;
6628e7931f94SStefano Zampini 
66292a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6630e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6631e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6632e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
663370cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6634e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6635e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6636e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6637e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6638e7931f94SStefano Zampini   }
663928143c3dSStefano Zampini #endif
6640e7931f94SStefano Zampini 
664128143c3dSStefano Zampini   /* assemble new additional is (if any) */
664228143c3dSStefano Zampini   if (nis) {
664328143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
664428143c3dSStefano Zampini 
664528143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6646854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
664728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
664828143c3dSStefano Zampini     psum = 0;
664928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
665028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
665128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
665228143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
665328143c3dSStefano Zampini         psum += plen;
665428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
665528143c3dSStefano Zampini       }
665628143c3dSStefano Zampini     }
6657854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6658854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
665928143c3dSStefano Zampini     for (i=1;i<nis;i++) {
666028143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
666128143c3dSStefano Zampini     }
666228143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
666328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
666428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
666528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
666628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
666728143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
666828143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
666928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
667028143c3dSStefano Zampini       }
667128143c3dSStefano Zampini     }
667228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
667328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
667428143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
667528143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
667628143c3dSStefano Zampini     }
667728143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
667828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
667928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
668028143c3dSStefano Zampini   }
6681e7931f94SStefano Zampini   /* free workspace */
668228143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6683e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6684e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6685e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6686e7931f94SStefano Zampini   if (isdense) {
6687e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6688e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6689e7931f94SStefano Zampini   } else {
6690e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6691e7931f94SStefano Zampini   }
669228143c3dSStefano Zampini   if (nis) {
669328143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
669428143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
669528143c3dSStefano Zampini   }
66961ae86dd6SStefano Zampini 
66971ae86dd6SStefano Zampini   if (nvecs) {
66981ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66991ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
67001ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67011ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
67021ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
67031ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
67041ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
67051ae86dd6SStefano Zampini     /* set values */
67061ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
67071ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
67081ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67091ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
67101ae86dd6SStefano Zampini       PetscInt j;
67111ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
67121ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
67131ae86dd6SStefano Zampini       }
67141ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
67151ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
67161ae86dd6SStefano Zampini     }
67171ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67181ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
67191ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
67201ae86dd6SStefano Zampini   }
67211ae86dd6SStefano Zampini 
67221ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
67231ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6724e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6725e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
67261ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
672728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6728e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6729e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
67301ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
673128143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6732e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6733e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6734e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6735e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6736e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
673728143c3dSStefano Zampini   if (nis) {
673828143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
673928143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
674028143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
674128143c3dSStefano Zampini   }
674228143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
674328143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
674428143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
674528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
674628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
674728143c3dSStefano Zampini     }
67481ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
67491ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
67501ae86dd6SStefano Zampini     }
675153a05cb3SStefano Zampini     *mat_n = NULL;
675228143c3dSStefano Zampini   }
6753e7931f94SStefano Zampini   PetscFunctionReturn(0);
6754e7931f94SStefano Zampini }
6755a57a6d2fSStefano Zampini 
675612edc857SStefano Zampini /* temporary hack into ksp private data structure */
6757af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
675812edc857SStefano Zampini 
6759c8587f34SStefano Zampini #undef __FUNCT__
6760c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6761c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6762c8587f34SStefano Zampini {
6763c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6764c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
676520a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
67661ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
67679881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
676820a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
67696e683305SStefano Zampini   IS                     coarse_is,*isarray;
67706e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
677130368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6772f9eb5b7dSStefano Zampini   PC                     pc_temp;
6773c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6774c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6775f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
67764f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
67776e683305SStefano Zampini   Mat                    t_coarse_mat_is;
677857de7509SStefano Zampini   PetscInt               ncoarse;
677968457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
678022bc73bbSStefano Zampini   PetscScalar            *array;
678157de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
678257de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
67839881197aSStefano Zampini   PetscErrorCode         ierr;
6784fdc09c96SStefano Zampini 
6785c8587f34SStefano Zampini   PetscFunctionBegin;
6786c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
678768457ee5SStefano 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 */
6788fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
67895a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6790fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6791f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6792f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6793f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6794fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
679551bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
679651bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6797dc4bcba2SStefano Zampini         PC        pc;
6798dc4bcba2SStefano Zampini         PetscBool isbddc;
6799dc4bcba2SStefano Zampini 
6800dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6801dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6802dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6803dc4bcba2SStefano Zampini         if (isbddc) {
680463c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
680563c961adSStefano Zampini         } else {
6806727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
680763c961adSStefano Zampini         }
6808fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6809fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6810fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6811f4ddd8eeSStefano Zampini       }
6812fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6813fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6814f4ddd8eeSStefano Zampini     }
681570cf5478SStefano Zampini     /* reset any subassembling information */
681657de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
681770cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
681857de7509SStefano Zampini     }
68196e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6820fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6821f4ddd8eeSStefano Zampini   }
682257de7509SStefano Zampini   /* assemble coarse matrix */
682357de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
682457de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
682557de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
682657de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
682718a45a71SStefano Zampini   } else {
682857de7509SStefano Zampini     coarse_mat = NULL;
682957de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
68306e683305SStefano Zampini   }
6831e7931f94SStefano Zampini 
6832abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6833abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6834abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6835abbbba34SStefano Zampini 
6836abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
683722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
683822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
683922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
684022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6841e176bc59SStefano 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);
68426e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
68436e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68446e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6845abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6846abbbba34SStefano Zampini 
684757de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
684857de7509SStefano Zampini   im_active = !!(pcis->n);
684957de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
685057de7509SStefano Zampini 
685114f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
685257de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
685357de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
685457de7509SStefano Zampini   coarse_mat_is = NULL;
685557de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
685657de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
685757de7509SStefano Zampini   full_restr = PETSC_TRUE;
68581ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
685957de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
686057de7509SStefano Zampini   if (multilevel_requested) {
686157de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
686257de7509SStefano Zampini     restr = PETSC_FALSE;
686357de7509SStefano Zampini     full_restr = PETSC_FALSE;
686457de7509SStefano Zampini   } else {
686557de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
686657de7509SStefano Zampini     restr = PETSC_TRUE;
686757de7509SStefano Zampini     full_restr = PETSC_TRUE;
686857de7509SStefano Zampini   }
68694b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
687057de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
687157de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6872a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
687357de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6874a198735bSStefano Zampini     } else {
6875a198735bSStefano Zampini       PetscMPIInt size,rank;
6876a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6877a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6878a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6879a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6880a198735bSStefano Zampini     }
688157de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
688257de7509SStefano Zampini     PetscInt    psum;
688357de7509SStefano Zampini     PetscMPIInt size;
688457de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
688557de7509SStefano Zampini     else psum = 0;
688657de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
688757de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
688857de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
688957de7509SStefano Zampini   }
689057de7509SStefano Zampini   /* determine if we can go multilevel */
689157de7509SStefano Zampini   if (multilevel_requested) {
689257de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
689357de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
689457de7509SStefano Zampini   }
689557de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
689657de7509SStefano Zampini 
6897e4d548c7SStefano Zampini   /* dump subassembling pattern */
6898e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6899e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6900e4d548c7SStefano Zampini   }
6901e4d548c7SStefano Zampini 
69026e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
6903c703fcc7SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
69046e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
69056e683305SStefano Zampini     const PetscInt         *idxs;
69066e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
69076e683305SStefano Zampini 
69086e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
69090be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
69106e683305SStefano Zampini     /* allocate space for temporary storage */
6911854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6912854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
69136e683305SStefano Zampini     /* allocate for IS array */
69146e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
69156e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
691627b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
691730368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6918854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
69196e683305SStefano Zampini     /* dofs splitting */
69206e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
69216e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
69226e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
69236e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69246e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69256e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69266e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
692730368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
69286e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
69296e683305SStefano Zampini     }
69306e683305SStefano Zampini     /* neumann boundaries */
69316e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
69326e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
69336e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
69346e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69356e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69366e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69376e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
693830368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
69396e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
69406e683305SStefano Zampini     }
69416e683305SStefano Zampini     /* free memory */
69426e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
69436e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
69446e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
69456e683305SStefano Zampini   } else {
69466e683305SStefano Zampini     nis = 0;
69476e683305SStefano Zampini     nisdofs = 0;
69486e683305SStefano Zampini     nisneu = 0;
694930368db7SStefano Zampini     nisvert = 0;
69506e683305SStefano Zampini     isarray = NULL;
69516e683305SStefano Zampini   }
69526e683305SStefano Zampini   /* destroy no longer needed map */
69536e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
69546e683305SStefano Zampini 
695557de7509SStefano Zampini   /* subassemble */
695657de7509SStefano Zampini   if (multilevel_allowed) {
69571ae86dd6SStefano Zampini     Vec       vp[1];
69581ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
695957de7509SStefano Zampini     PetscBool reuse,reuser;
69601ae86dd6SStefano Zampini 
696157de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
696257de7509SStefano Zampini     else reuse = PETSC_FALSE;
696357de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
69641ae86dd6SStefano Zampini     vp[0] = NULL;
69651ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
69661ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
69671ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
69681ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
69691ae86dd6SStefano Zampini       nvecs = 1;
69701ae86dd6SStefano Zampini 
69711ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6972a198735bSStefano Zampini         Mat      B,loc_divudotp;
69731ae86dd6SStefano Zampini         Vec      v,p;
69741ae86dd6SStefano Zampini         IS       dummy;
69751ae86dd6SStefano Zampini         PetscInt np;
69761ae86dd6SStefano Zampini 
6977a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6978a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
69791ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6980a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
69811ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
69821ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
69831ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
69841ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
69851ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
69861ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
69871ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
69881ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
69891ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
69901ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
69911ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
69921ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
699374e2c79eSStefano Zampini       }
69941ae86dd6SStefano Zampini     }
69951ae86dd6SStefano Zampini     if (reuser) {
69961ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
699774e2c79eSStefano Zampini     } else {
69981ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp);CHKERRQ(ierr);
69991ae86dd6SStefano Zampini     }
70001ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
70011ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
70021ae86dd6SStefano Zampini       PetscInt    nl;
70031ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
70041ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
70051ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
70061ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
70071ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
70081ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
70091ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
70101ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7011a198735bSStefano Zampini     } else {
7012a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
70131ae86dd6SStefano Zampini     }
70141ae86dd6SStefano Zampini   } else {
70151ae86dd6SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,0,NULL);CHKERRQ(ierr);
70166e683305SStefano Zampini   }
701757de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
701857de7509SStefano Zampini     PetscMPIInt size;
701957de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
702057de7509SStefano Zampini     if (!multilevel_allowed) {
702157de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
70226e683305SStefano Zampini     } else {
702357de7509SStefano Zampini       Mat A;
7024779c1cceSStefano Zampini 
702557de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
702657de7509SStefano Zampini       if (coarse_mat_is) {
702757de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
702857de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
702957de7509SStefano Zampini         coarse_mat = coarse_mat_is;
703057de7509SStefano Zampini       }
703157de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
703257de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
703357de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7034779c1cceSStefano Zampini     }
7035779c1cceSStefano Zampini   }
703657de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
703757de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
70386e683305SStefano Zampini 
70396e683305SStefano Zampini   /* create local to global scatters for coarse problem */
704068457ee5SStefano Zampini   if (compute_vecs) {
70416e683305SStefano Zampini     PetscInt lrows;
70426e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
704357de7509SStefano Zampini     if (coarse_mat) {
704457de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
70456e683305SStefano Zampini     } else {
70466e683305SStefano Zampini       lrows = 0;
70476e683305SStefano Zampini     }
70486e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
70496e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
70506e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
70516e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70526e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70536e683305SStefano Zampini   }
70546e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7055c8587f34SStefano Zampini 
7056f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7057f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7058f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7059f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7060f9eb5b7dSStefano Zampini   } else {
7061f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7062f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7063c8587f34SStefano Zampini   }
7064c8587f34SStefano Zampini 
70656e683305SStefano Zampini   /* print some info if requested */
70666e683305SStefano Zampini   if (pcbddc->dbg_flag) {
70676e683305SStefano Zampini     if (!multilevel_allowed) {
70686e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
70696e683305SStefano Zampini       if (multilevel_requested) {
70706e683305SStefano 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);
70716e683305SStefano Zampini       } else if (pcbddc->max_levels) {
70726e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
70736e683305SStefano Zampini       }
70746e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
70756e683305SStefano Zampini     }
70766e683305SStefano Zampini   }
70776e683305SStefano Zampini 
7078f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
707957de7509SStefano Zampini   if (coarse_mat) {
70806a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
70816e683305SStefano Zampini     if (pcbddc->dbg_flag) {
708257de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
70836e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
70846e683305SStefano Zampini     }
7085f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7086312be037SStefano Zampini       char prefix[256],str_level[16];
7087e604994aSStefano Zampini       size_t len;
708857de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7089422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7090c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7091f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
709257de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7093c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
70946e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7095c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
7096c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7097e604994aSStefano Zampini       /* prefix */
7098e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7099e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7100e604994aSStefano Zampini       if (!pcbddc->current_level) {
7101e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7102e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7103c8587f34SStefano Zampini       } else {
7104e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7105312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7106312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
710734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7108312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7109e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7110e604994aSStefano Zampini       }
7111e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
71123e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
71133e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
71143e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
71153e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7116f9eb5b7dSStefano Zampini       /* allow user customization */
7117f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
71183e3c6dadSStefano Zampini     }
71193e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
712051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
71213e3c6dadSStefano Zampini     if (nisdofs) {
71223e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
71233e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
71243e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
71253e3c6dadSStefano Zampini       }
71263e3c6dadSStefano Zampini     }
71273e3c6dadSStefano Zampini     if (nisneu) {
71283e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
71293e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7130312be037SStefano Zampini     }
713130368db7SStefano Zampini     if (nisvert) {
713230368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
713330368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
713430368db7SStefano Zampini     }
7135f9eb5b7dSStefano Zampini 
7136f9eb5b7dSStefano Zampini     /* get some info after set from options */
7137f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7138f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
71394f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
71406e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7141f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7142f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7143f9eb5b7dSStefano Zampini     }
714439f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
71454f3a063dSStefano Zampini     if (isredundant) {
71464f3a063dSStefano Zampini       KSP inner_ksp;
71474f3a063dSStefano Zampini       PC  inner_pc;
71484f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
71494f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
71504f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
71514f3a063dSStefano Zampini     }
7152f9eb5b7dSStefano Zampini 
715357de7509SStefano Zampini     /* parameters which miss an API */
715457de7509SStefano Zampini     if (isbddc) {
7155720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7156720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
715757de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
715827b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
715927b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7160a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7161a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7162a198735bSStefano Zampini         IS                     row,col;
7163a198735bSStefano Zampini         const PetscInt         *gidxs;
7164a198735bSStefano Zampini         PetscInt               n,st,M,N;
7165a198735bSStefano Zampini 
7166a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7167a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7168a198735bSStefano Zampini         st = st-n;
7169a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7170a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7171a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7172a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7173a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7174a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7175a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7176a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7177a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7178a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7179a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7180a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7181a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7182a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7183a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7184a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7185a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7186a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7187a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7188a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
71898ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7190a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7191720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
719259e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7193720d30f9SStefano Zampini       }
7194d4d8cf7bSStefano Zampini     }
71959881197aSStefano Zampini 
71963301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
71975a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
71983301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
71993301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
72003301b35fSStefano Zampini     }
72013301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
72023301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
72033301b35fSStefano Zampini     }
72043301b35fSStefano Zampini     if (pc->pmat->spd_set) {
72053301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
72063301b35fSStefano Zampini     }
720727b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
720827b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
720927b6a85dSStefano Zampini     }
72106e683305SStefano Zampini     /* set operators */
72115f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
72126e683305SStefano Zampini     if (pcbddc->dbg_flag) {
72136e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
72146e683305SStefano Zampini     }
72156e683305SStefano Zampini   }
72166e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7217b1ecc7b1SStefano Zampini #if 0
7218b9b85e73SStefano Zampini   {
7219b9b85e73SStefano Zampini     PetscViewer viewer;
7220b9b85e73SStefano Zampini     char filename[256];
7221b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7222b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
72236a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7224b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7225f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7226b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7227b9b85e73SStefano Zampini   }
7228b9b85e73SStefano Zampini #endif
7229f9eb5b7dSStefano Zampini 
723098a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
723198a51de6SStefano Zampini     Vec crhs,csol;
723204708bb6SStefano Zampini 
7233f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7234f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7235f347579bSStefano Zampini     if (!csol) {
72362a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7237f9eb5b7dSStefano Zampini     }
7238f347579bSStefano Zampini     if (!crhs) {
72392a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7240f347579bSStefano Zampini     }
7241b0f5fe93SStefano Zampini   }
72421ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7243b0f5fe93SStefano Zampini 
7244b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7245b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7246b0f5fe93SStefano Zampini 
7247b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
72484f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
72494f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
72504f1b2e48SStefano Zampini     }
7251b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7252b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7253b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7254b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7255b0f5fe93SStefano Zampini     if (coarse_mat) {
7256b0f5fe93SStefano Zampini       Vec         nullv;
7257b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7258b0f5fe93SStefano Zampini       PetscInt    nl;
7259b0f5fe93SStefano Zampini 
7260b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7261b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7262b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7263b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7264b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7265b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7266b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7267b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7268b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7269b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7270b0f5fe93SStefano Zampini     }
7271b0f5fe93SStefano Zampini   }
7272b0f5fe93SStefano Zampini 
7273b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7274b0f5fe93SStefano Zampini     PetscBool ispreonly;
7275b0f5fe93SStefano Zampini 
7276b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7277b0f5fe93SStefano Zampini       PetscBool isnull;
7278b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7279bef83e63SStefano Zampini       if (isnull) {
7280b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7281b0f5fe93SStefano Zampini       }
7282bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7283b0f5fe93SStefano Zampini     }
7284b0f5fe93SStefano Zampini     /* setup coarse ksp */
7285b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7286cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7287cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
72886e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7289c8587f34SStefano Zampini       KSP       check_ksp;
72902b510759SStefano Zampini       KSPType   check_ksp_type;
7291c8587f34SStefano Zampini       PC        check_pc;
72926e683305SStefano Zampini       Vec       check_vec,coarse_vec;
72936a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
72942b510759SStefano Zampini       PetscInt  its;
72956e683305SStefano Zampini       PetscBool compute_eigs;
72966e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
72976e683305SStefano Zampini       PetscInt  neigs;
72988e185a42SStefano Zampini       const char *prefix;
7299c8587f34SStefano Zampini 
73002b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
73016e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7302422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
730323ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7304f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7305e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7306e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7307e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
73082b510759SStefano Zampini       if (ispreonly) {
73092b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
73106e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
73112b510759SStefano Zampini       } else {
7312cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
73136e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7314c8587f34SStefano Zampini       }
7315c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
73166e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
73176e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
73186e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7319a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7320a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7321a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7322a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7323c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7324c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7325c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7326c8587f34SStefano Zampini       /* create random vec */
73272701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7328c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
73296e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7330c8587f34SStefano Zampini       /* solve coarse problem */
73316e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7332cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
73336e683305SStefano Zampini       if (compute_eigs) {
7334854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7335854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
73366e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
73371ae86dd6SStefano Zampini         if (neigs) {
73386e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
73396e683305SStefano Zampini           lambda_min = eigs_r[0];
73406e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
73412701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
73422701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7343cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7344cbcc2c2aSStefano Zampini             }
7345c8587f34SStefano Zampini           }
7346c8587f34SStefano Zampini         }
73471ae86dd6SStefano Zampini       }
7348cbcc2c2aSStefano Zampini 
7349c8587f34SStefano Zampini       /* check coarse problem residual error */
73506e683305SStefano Zampini       if (pcbddc->dbg_flag) {
73516e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
73526e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73536e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7354c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
73556e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
73566e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7357779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
73586e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
73596e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
73606e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
73616e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7362b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7363b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7364b0f5fe93SStefano Zampini         }
73656e683305SStefano Zampini         if (compute_eigs) {
73666e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7367deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7368c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
73696e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
73706e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %d iterations of %s): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,lambda_min,lambda_max,lambda_min_s,lambda_max_s);CHKERRQ(ierr);
73716e683305SStefano Zampini           for (i=0;i<neigs;i++) {
73726e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7373c8587f34SStefano Zampini           }
73746e683305SStefano Zampini         }
73756e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
73766e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73776e683305SStefano Zampini       }
7378e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
73792701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7380c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
73816e683305SStefano Zampini       if (compute_eigs) {
73826e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
73836e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7384c8587f34SStefano Zampini       }
73856e683305SStefano Zampini     }
73866e683305SStefano Zampini   }
7387bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7388cbcc2c2aSStefano Zampini   /* print additional info */
7389cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
73906e683305SStefano Zampini     /* waits until all processes reaches this point */
73916e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7392cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7393cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7394cbcc2c2aSStefano Zampini   }
7395cbcc2c2aSStefano Zampini 
73962b510759SStefano Zampini   /* free memory */
7397fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7398c8587f34SStefano Zampini   PetscFunctionReturn(0);
7399c8587f34SStefano Zampini }
7400674ae819SStefano Zampini 
7401f34684f1SStefano Zampini #undef __FUNCT__
7402f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7403f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7404f34684f1SStefano Zampini {
7405f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7406f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7407f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7408dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7409dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
741073be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7411dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7412f34684f1SStefano Zampini   PetscErrorCode ierr;
7413f34684f1SStefano Zampini 
7414f34684f1SStefano Zampini   PetscFunctionBegin;
7415f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
74166c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7417dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
74183bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7419dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7420dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
74216583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7422dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7423dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7424dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
74256c4ed002SBarry 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);
7426dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7427dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7428dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7429dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7430dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7431f34684f1SStefano Zampini 
7432f34684f1SStefano Zampini   /* check numbering */
7433f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7434019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7435dc456d91SStefano Zampini     PetscInt    i;
7436b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7437f34684f1SStefano Zampini 
7438f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7439f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7440f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
74411575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7442019a44ceSStefano Zampini     /* counter */
7443019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7444019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7445019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7446019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7447019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7448019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7449f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7450f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7451727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7452f34684f1SStefano Zampini     }
7453f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7454f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7455f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7456e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7457e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7458e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7459e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7460f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7461019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7462f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7463019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
74642c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
746575c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7466b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
74672c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
74682c66d082SStefano 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);
7469f34684f1SStefano Zampini       }
7470f34684f1SStefano Zampini     }
7471019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7472b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7473f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7474f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7475f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7476f34684f1SStefano Zampini     }
7477f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7478f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7479e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7480e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7481f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7482f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7483b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7484ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7485ca8b9ea9SStefano Zampini 
7486ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
74873bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7488f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7489f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7490f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7491f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
74924bc2dc4bSStefano 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);
7493f34684f1SStefano Zampini       }
7494f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7495ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7496f34684f1SStefano Zampini     }
7497f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74981575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7499302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7500f34684f1SStefano Zampini   }
75018bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7502f34684f1SStefano Zampini   /* get back data */
7503f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7504f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7505674ae819SStefano Zampini   PetscFunctionReturn(0);
7506674ae819SStefano Zampini }
7507674ae819SStefano Zampini 
7508e456f2a8SStefano Zampini #undef __FUNCT__
7509e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7510a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7511e456f2a8SStefano Zampini {
7512e456f2a8SStefano Zampini   IS             localis_t;
7513a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7514e456f2a8SStefano Zampini   PetscScalar    *vals;
7515e456f2a8SStefano Zampini   PetscErrorCode ierr;
7516e456f2a8SStefano Zampini 
7517e456f2a8SStefano Zampini   PetscFunctionBegin;
7518a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7519e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7520854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7521e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7522e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7523a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7524a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
75251035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7526a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
75271035eff8SStefano Zampini   }
7528a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7529e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7530e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7531a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7532a7dc3881SStefano Zampini   /* now compute set in local ordering */
7533a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7534a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7535a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7536a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7537a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7538ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7539e456f2a8SStefano Zampini       lsize++;
7540e456f2a8SStefano Zampini     }
7541e456f2a8SStefano Zampini   }
7542854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7543a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7544ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7545e456f2a8SStefano Zampini       idxs[lsize++] = i;
7546e456f2a8SStefano Zampini     }
7547e456f2a8SStefano Zampini   }
7548a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7549a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7550e456f2a8SStefano Zampini   *localis = localis_t;
7551e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7552e456f2a8SStefano Zampini }
7553906d46d4SStefano Zampini 
7554b96c3477SStefano Zampini #undef __FUNCT__
7555b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
755608122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7557b96c3477SStefano Zampini {
7558a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7559b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7560b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7561a64f4aa4SStefano Zampini   Mat                 S_j;
7562b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7563b96c3477SStefano Zampini   PetscBool           free_used_adj;
7564b96c3477SStefano Zampini   PetscErrorCode      ierr;
7565b96c3477SStefano Zampini 
7566b96c3477SStefano Zampini   PetscFunctionBegin;
7567b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7568b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
756908122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7570b96c3477SStefano Zampini     used_xadj = NULL;
7571b96c3477SStefano Zampini     used_adjncy = NULL;
7572b96c3477SStefano Zampini   } else {
757308122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
757408122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
757508122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
757608122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7577b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7578b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7579b96c3477SStefano Zampini     } else {
75802fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7581b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7582b96c3477SStefano Zampini       PetscInt       nvtxs;
7583b96c3477SStefano Zampini 
75842fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
75852fffb893SStefano Zampini       if (flg_row) {
7586b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7587b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7588b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7589b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
75902fffb893SStefano Zampini       } else {
75912fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
75922fffb893SStefano Zampini         used_xadj = NULL;
75932fffb893SStefano Zampini         used_adjncy = NULL;
75942fffb893SStefano Zampini       }
75952fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7596b96c3477SStefano Zampini     }
7597b96c3477SStefano Zampini   }
7598d5574798SStefano Zampini 
7599d5574798SStefano Zampini   /* setup sub_schurs data */
7600a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7601df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7602df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7603a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
760491af6908SStefano 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);
7605a64f4aa4SStefano Zampini   } else {
76066816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
76074d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7608a3df083aSStefano Zampini     PetscInt  benign_n;
760972b8c272SStefano Zampini     Mat       change = NULL;
76109d54b7f4SStefano Zampini     Vec       scaling = NULL;
761172b8c272SStefano Zampini     IS        change_primal = NULL;
7612a3df083aSStefano Zampini 
76135feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
76145feab87aSStefano Zampini       PetscInt n_vertices;
76155feab87aSStefano Zampini 
76165feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
76172034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
76185feab87aSStefano Zampini     }
761904708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
762004708bb6SStefano Zampini     if (!isseqaij) {
762104708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
762204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
762304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
762404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
762504708bb6SStefano Zampini       } else {
7626511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
762704708bb6SStefano Zampini       }
762804708bb6SStefano Zampini     }
7629a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7630a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7631ca92afb2SStefano Zampini     } else {
7632a3df083aSStefano Zampini       benign_n = 0;
7633ca92afb2SStefano Zampini     }
7634b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7635b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7636b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
763772b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
763822db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7639b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
764022db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7641b7ab4a40SStefano Zampini     }
7642b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7643b7ab4a40SStefano 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 */
7644b7ab4a40SStefano Zampini     if (need_change) {
764588c03ad3SStefano Zampini       PC_IS   *pcisf;
764688c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
764788c03ad3SStefano Zampini       PC      pcf;
764888c03ad3SStefano Zampini 
7649e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
765088c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
765188c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
765288c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
765388c03ad3SStefano Zampini       /* hacks */
765488c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
765572b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
765672b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
765772b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
765872b8c272SStefano Zampini       pcisf->n = pcis->n;
765972b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
766088c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
766188c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
766288c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
766388c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
766488c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
766588c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
766672b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
766788c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
766888c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
766972b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
767072b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
767172b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
767272b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
767372b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
767488c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
767572b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
767688c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
767788c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
767888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
767988c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
768088c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
768188c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
768288c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
768388c03ad3SStefano Zampini     }
76849d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
768591af6908SStefano 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);
768672b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
768772b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7688ca92afb2SStefano Zampini   }
7689d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7690b96c3477SStefano Zampini 
7691b96c3477SStefano Zampini   /* free adjacency */
7692b96c3477SStefano Zampini   if (free_used_adj) {
7693b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7694b96c3477SStefano Zampini   }
7695b96c3477SStefano Zampini   PetscFunctionReturn(0);
7696b96c3477SStefano Zampini }
7697b96c3477SStefano Zampini 
7698b96c3477SStefano Zampini #undef __FUNCT__
7699b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
770008122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7701b96c3477SStefano Zampini {
7702b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7703b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7704b96c3477SStefano Zampini   PCBDDCGraph         graph;
7705b96c3477SStefano Zampini   PetscErrorCode      ierr;
7706b96c3477SStefano Zampini 
7707b96c3477SStefano Zampini   PetscFunctionBegin;
7708b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
770908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
77103301b35fSStefano Zampini     IS       verticesIS,verticescomm;
77113301b35fSStefano Zampini     PetscInt vsize,*idxs;
7712b96c3477SStefano Zampini 
7713b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
77143301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
77153301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
77163301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
77173301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7718c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7719b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7720be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7721441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
77223301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7723b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7724b96c3477SStefano Zampini   } else {
7725b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7726b96c3477SStefano Zampini   }
7727e4d548c7SStefano Zampini   /* print some info */
7728e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7729e4d548c7SStefano Zampini     IS       vertices;
7730e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7731c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7732e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7733e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7734e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7735e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7736e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7737e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7738e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7739e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7740e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7741c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7742e4d548c7SStefano Zampini   }
7743b96c3477SStefano Zampini 
7744b96c3477SStefano Zampini   /* sub_schurs init */
7745b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7746b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7747b334f244SStefano Zampini   }
7748b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7749a64f4aa4SStefano Zampini 
7750b96c3477SStefano Zampini   /* free graph struct */
775108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7752b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7753b96c3477SStefano Zampini   }
7754b96c3477SStefano Zampini   PetscFunctionReturn(0);
7755b96c3477SStefano Zampini }
7756fa34dd3eSStefano Zampini 
7757fa34dd3eSStefano Zampini #undef __FUNCT__
7758fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7759fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7760fa34dd3eSStefano Zampini {
7761fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7762fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7763fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7764fa34dd3eSStefano Zampini 
7765fa34dd3eSStefano Zampini   PetscFunctionBegin;
7766fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7767fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
77684f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7769fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
77704f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
777175c01103SStefano Zampini     PetscReal      norm;
7772fa34dd3eSStefano Zampini     PetscInt       i;
7773fa34dd3eSStefano Zampini 
7774fa34dd3eSStefano Zampini     /* B0 and B0_B */
7775fa34dd3eSStefano Zampini     if (zerodiag) {
7776fa34dd3eSStefano Zampini       IS       dummy;
7777fa34dd3eSStefano Zampini 
77784f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
77794f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7780fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7781fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7782fa34dd3eSStefano Zampini     }
7783fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7784fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7785fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7786fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7787fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7788fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7789fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7790fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7791fa34dd3eSStefano Zampini     /* S_j */
7792fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7793fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7794fa34dd3eSStefano Zampini 
7795fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7796fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7797fa34dd3eSStefano Zampini     /* continuous in primal space */
7798fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7799fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7800fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7801fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
78024f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
78034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7804fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7805fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7806fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7807fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7808fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7809fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7810fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7811fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7812fa34dd3eSStefano Zampini 
7813fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7814fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7815fa34dd3eSStefano Zampini     /* local with Schur */
7816fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7817fa34dd3eSStefano Zampini     if (zerodiag) {
7818fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78194f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7820fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7821fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7822fa34dd3eSStefano Zampini     }
7823fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7824fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7825fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7826fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7827fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7828fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7829fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7830fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7831fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7832fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7833fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7834fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7835fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7836fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7837fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7838fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7839fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7840fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7841fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7842fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7843fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7844fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7845fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7846fa34dd3eSStefano Zampini     if (zerodiag) {
7847fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7848fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78494f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7850fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7851fa34dd3eSStefano Zampini     }
7852fa34dd3eSStefano Zampini     /* BDDC */
7853fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7854fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7855fa34dd3eSStefano Zampini 
7856fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7857fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7858fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7859fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
78604f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
78614f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7862fa34dd3eSStefano Zampini     }
78634f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7864fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7865fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7866fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7867fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7868fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7869fa34dd3eSStefano Zampini   }
7870fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7871fa34dd3eSStefano Zampini }
7872