xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision c703fcc73db5d316931899259999304887a9a8a3)
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;
1114e64d54eSstefano_zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe;
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 
261a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
2624e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
2634e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
264a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
265a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
266a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
267c2151214SStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
268a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
269a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
270a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
271c2151214SStefano Zampini     IS is;
272c2151214SStefano Zampini 
273c2151214SStefano Zampini     if (fl2g) {
274c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
275c2151214SStefano Zampini     } else {
276c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
277c2151214SStefano Zampini     }
278c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
279c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
280a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
281a13144ffSStefano Zampini       if (idxs[i] >= 0) {
282a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
283a13144ffSStefano Zampini       }
284a13144ffSStefano Zampini     }
285c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
286c2151214SStefano Zampini     if (fl2g) {
287c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
288c2151214SStefano Zampini     }
289a13144ffSStefano Zampini   }
290a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
291c2151214SStefano Zampini     IS is;
292c2151214SStefano Zampini 
293c2151214SStefano Zampini     if (fl2g) {
294c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
295c2151214SStefano Zampini     } else {
296c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
297c2151214SStefano Zampini     }
298c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
299c2151214SStefano Zampini     ierr = ISGetIndices(is,&idxs);CHKERRQ(ierr);
300a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
301a13144ffSStefano Zampini       if (idxs[i] >= 0) {
302a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
303a13144ffSStefano Zampini       }
304a13144ffSStefano Zampini     }
305c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
306c2151214SStefano Zampini     if (fl2g) {
307c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
308a13144ffSStefano Zampini     }
309c2151214SStefano Zampini   }
310c2151214SStefano Zampini 
311a13144ffSStefano Zampini   /* need to remove coarse faces' dofs to ensure the
312a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
313a13144ffSStefano Zampini   ierr = PetscCalloc1(ne,&marks);CHKERRQ(ierr);
31462b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
315a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
31662b0c6f7SStefano Zampini   for (i=1;i<n_neigh;i++)
31762b0c6f7SStefano Zampini     for (j=0;j<n_shared[i];j++)
31862b0c6f7SStefano Zampini       marks[shared[i][j]]++;
319a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
32062b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
32162b0c6f7SStefano Zampini     if (marks[i] > 1 || (marks[i] == 1 && PetscBTLookup(btb,i))) {
32262b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
32362b0c6f7SStefano Zampini     }
32462b0c6f7SStefano Zampini   }
32562b0c6f7SStefano Zampini 
32662b0c6f7SStefano Zampini   if (!conforming) {
32762b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
32862b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
32962b0c6f7SStefano Zampini   }
3304e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
331dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
33262b0c6f7SStefano Zampini   cum  = 0;
333a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
334dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
33562b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
336a13144ffSStefano Zampini       marks[cum++] = i;
337dec27d64SStefano Zampini       continue;
338dec27d64SStefano Zampini     }
339dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
34062b0c6f7SStefano Zampini     if (!conforming) {
34162b0c6f7SStefano Zampini       if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */
342a13144ffSStefano Zampini         marks[cum++] = i;
343a13144ffSStefano Zampini         ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
344a13144ffSStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
345a13144ffSStefano Zampini           ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
346a13144ffSStefano Zampini         }
34762b0c6f7SStefano Zampini       } else {
34862b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
34962b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
35062b0c6f7SStefano Zampini            - at most 2 endpoints
35162b0c6f7SStefano Zampini            - order-1 interior nodal dofs
35262b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
35362b0c6f7SStefano Zampini         */
35462b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
35562b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
35662b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
35762b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
35862b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
35962b0c6f7SStefano Zampini           if (nconn > order) ends++;
36062b0c6f7SStefano Zampini           else if (nconn == order) ints++;
36162b0c6f7SStefano Zampini           else undef++;
36262b0c6f7SStefano Zampini         }
36362b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
36462b0c6f7SStefano Zampini           marks[cum++] = i;
36562b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
36662b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
36762b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
36862b0c6f7SStefano Zampini           }
36962b0c6f7SStefano Zampini         }
37062b0c6f7SStefano Zampini       }
371a13144ffSStefano Zampini     }
372dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
373dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
374dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
375dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
376a13144ffSStefano Zampini     }
377dec27d64SStefano Zampini   }
37862b0c6f7SStefano Zampini   ierr = PetscBTDestroy(&btee);CHKERRQ(ierr);
379dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
3804e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
38162b0c6f7SStefano Zampini   if (!conforming) {
38262b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
38362b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
38462b0c6f7SStefano Zampini   }
3854e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
386a13144ffSStefano Zampini   /* identify splitpoints and corner candidates: TODO variable order */
3874e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
388a13144ffSStefano Zampini   if (print) {
3894e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
3904e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
3914e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
392a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
393a13144ffSStefano Zampini   }
394a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
395dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
396a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
397dec27d64SStefano Zampini     PetscInt ord = order, test = ii[i+1]-ii[i];
398dec27d64SStefano Zampini     if (!order) {
399dec27d64SStefano Zampini       PetscReal vorder = 0.;
400dec27d64SStefano Zampini 
401dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
402dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
403dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
404dec27d64SStefano Zampini       ord  = 1;
405dec27d64SStefano Zampini     }
406a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
407dec27d64SStefano 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);
408a13144ffSStefano Zampini #endif
409dec27d64SStefano Zampini     if (test >= 3*ord) { /* splitpoints */
410a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
411a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
412dec27d64SStefano Zampini     } else if (test == ord) {
413a13144ffSStefano Zampini       if (order == 1) {
414a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
415a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
416a13144ffSStefano Zampini       } else {
417a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
418a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
419a13144ffSStefano Zampini       }
420a13144ffSStefano Zampini     }
421a13144ffSStefano Zampini   }
422dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
423a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
424a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
425a13144ffSStefano Zampini 
426a13144ffSStefano Zampini   /* Get the local G^T explicitly */
427a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
4284e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
429a13144ffSStefano Zampini   if (print) {
430a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"initial_lGt");CHKERRQ(ierr);
431a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
432a13144ffSStefano Zampini   }
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           if (print) PetscPrintf(PETSC_COMM_SELF,"      candidate? %d\n",(PetscBool)(PetscBTLookup(btvcand,jj[k])));
656a13144ffSStefano Zampini           PetscInt  k2;
657a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
658a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
659c2151214SStefano 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]));
660c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
661c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
662c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
663a13144ffSStefano Zampini               corner = PETSC_TRUE;
664a13144ffSStefano Zampini               break;
665a13144ffSStefano Zampini             }
666a13144ffSStefano Zampini           }
667a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
668a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
669a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
670a13144ffSStefano Zampini           } else {
671a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
672a13144ffSStefano Zampini           }
673a13144ffSStefano Zampini         }
674a13144ffSStefano Zampini       }
675a13144ffSStefano Zampini     }
676a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
677a13144ffSStefano Zampini   }
678a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
679a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
680c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
681a13144ffSStefano Zampini 
682a13144ffSStefano Zampini   /* Reset marked primal dofs */
683a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
684a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
685a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
686a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
687a13144ffSStefano Zampini 
688a13144ffSStefano Zampini   /* Compute extended cols indices */
689a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG ,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
690a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
691a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
692a13144ffSStefano Zampini   i   *= maxsize;
693a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extcols);CHKERRQ(ierr);
694a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&emarks);CHKERRQ(ierr);
695a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
696a13144ffSStefano Zampini   eerr = PETSC_FALSE;
697a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
698a13144ffSStefano Zampini     PetscInt size;
699a13144ffSStefano Zampini 
700a13144ffSStefano Zampini     cum  = 0;
701a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
702a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
703a13144ffSStefano Zampini     for (j=0;j<size;j++) {
704a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
705a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
706a13144ffSStefano Zampini     }
707a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
708a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
709a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
710a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
711a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
712a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
713a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
714a13144ffSStefano Zampini     if (cum != size -1) {
715a13144ffSStefano Zampini       emarks[i] = 1;
716a13144ffSStefano Zampini       if (print) {
717a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
718a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
719a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
720a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
721a13144ffSStefano Zampini       }
722a13144ffSStefano Zampini       eerr = PETSC_TRUE;
723a13144ffSStefano Zampini     }
724a13144ffSStefano Zampini   }
7254e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
726a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
727a13144ffSStefano Zampini   if (done) {
728a13144ffSStefano Zampini     PetscInt *newprimals;
729a13144ffSStefano Zampini 
730a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
731a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
732a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
733a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
734a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
735a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
736a13144ffSStefano Zampini       if (emarks[i]) {
737a13144ffSStefano Zampini         PetscInt size,mark = i+1;
738a13144ffSStefano Zampini 
739a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
740a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
741c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
742a13144ffSStefano Zampini         for (j=0;j<size;j++) {
743a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
744a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
745a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
746a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
747a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
748a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
749a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
750a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
751a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
752a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
753a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
754a13144ffSStefano Zampini                   /* finally set the new corners */
755a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
756a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
757a13144ffSStefano Zampini                   }
758a13144ffSStefano Zampini                 }
759a13144ffSStefano Zampini               }
760a13144ffSStefano Zampini             }
761a13144ffSStefano Zampini           }
762a13144ffSStefano Zampini         }
763a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
764a13144ffSStefano Zampini       }
765a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
766a13144ffSStefano Zampini     }
767a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
768c2151214SStefano Zampini     if (fl2g) {
769c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
770c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
771c2151214SStefano Zampini       for (i=0;i<nee;i++) {
772c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
773c2151214SStefano Zampini       }
774c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
775c2151214SStefano Zampini     }
776c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
777a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
778a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
779a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
780a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
781a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
782c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
783c2151214SStefano Zampini     if (fl2g) {
784c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
785c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
786c2151214SStefano Zampini       for (i=0;i<nee;i++) {
787c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
788c2151214SStefano Zampini       }
789c2151214SStefano Zampini     } else {
790c2151214SStefano Zampini       eedges  = alleedges;
791c2151214SStefano Zampini       primals = allprimals;
792c2151214SStefano Zampini     }
793a13144ffSStefano Zampini 
794a13144ffSStefano Zampini     /* Mark again */
795a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
796a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
797a13144ffSStefano Zampini       PetscInt size,mark = i+1;
798a13144ffSStefano Zampini 
799a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
800a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
801a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
802a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
803a13144ffSStefano Zampini     }
804a13144ffSStefano Zampini     if (print) {
805a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
806a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
807a13144ffSStefano Zampini     }
808a13144ffSStefano Zampini 
809a13144ffSStefano Zampini     /* Recompute extended cols */
810a13144ffSStefano Zampini     eerr = PETSC_FALSE;
811a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
812a13144ffSStefano Zampini       PetscInt size;
813a13144ffSStefano Zampini 
814a13144ffSStefano Zampini       cum  = 0;
815a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
816a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
817a13144ffSStefano Zampini       for (j=0;j<size;j++) {
818a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
819a13144ffSStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) {
820a13144ffSStefano Zampini           if (!PetscBTLookup(btv,jj[k])) {
821a13144ffSStefano Zampini             extrow[cum++] = jj[k];
822a13144ffSStefano Zampini           }
823a13144ffSStefano Zampini         }
824a13144ffSStefano Zampini       }
825a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
826a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
827a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
828a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
829a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
830a13144ffSStefano Zampini       if (cum != size -1) {
831a13144ffSStefano Zampini         if (print) {
832a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
833a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
834a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
835a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
836a13144ffSStefano Zampini         }
837a13144ffSStefano Zampini         eerr = PETSC_TRUE;
838a13144ffSStefano Zampini       }
839a13144ffSStefano Zampini     }
840a13144ffSStefano Zampini   }
841a13144ffSStefano Zampini   ierr = MatRestoreRowIJ( lG,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
842a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
843a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
844a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
845a13144ffSStefano Zampini   /* an error should not occur at this point */
846a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
847a13144ffSStefano Zampini 
8484e64d54eSstefano_zampini   /* Check the number of endpoints */
849c2151214SStefano Zampini   /* TODO: fix case for circular edge */
8504e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
8514e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8524e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
8534e64d54eSstefano_zampini     PetscInt size, found = 0;
8544e64d54eSstefano_zampini 
8554e64d54eSstefano_zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
8564e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8574e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
8584e64d54eSstefano_zampini     for (j=0;j<size;j++) {
8594e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
8604e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8614e64d54eSstefano_zampini         PetscInt vv = jj[k];
8624e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
8634e64d54eSstefano_zampini           found++;
8644e64d54eSstefano_zampini         }
8654e64d54eSstefano_zampini       }
8664e64d54eSstefano_zampini     }
8674e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
8684e64d54eSstefano_zampini     if (found != 2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d\n",found,i);
8694e64d54eSstefano_zampini   }
8704e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8714e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
8724e64d54eSstefano_zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
8734e64d54eSstefano_zampini 
874a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
875a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
876a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
877a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
878a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
879a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
880a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
881a13144ffSStefano Zampini 
882a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
883a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
884a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
885a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
886a13144ffSStefano Zampini       if (emax < emarks[j]) {
887a13144ffSStefano Zampini         emax = emarks[j];
888a13144ffSStefano Zampini         eemax = j;
889a13144ffSStefano Zampini       }
890a13144ffSStefano Zampini     }
891a13144ffSStefano Zampini     /* not relevant for edges */
892a13144ffSStefano Zampini     if (!eemax) continue;
893a13144ffSStefano Zampini 
894a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
895a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
896c2151214SStefano 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]);
897a13144ffSStefano Zampini       }
898a13144ffSStefano Zampini     }
899a13144ffSStefano Zampini   }
900a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
901a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
902a13144ffSStefano Zampini #endif
903a13144ffSStefano Zampini 
904a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
905a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
906a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
907a13144ffSStefano Zampini   extmem *= maxsize;
908a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
909a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
910a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
911a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
912a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
913a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
914a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
915a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
916a13144ffSStefano Zampini         mark = marks[jj[j]];
917a13144ffSStefano Zampini 
918a13144ffSStefano Zampini     /* not relevant */
919a13144ffSStefano Zampini     if (!mark) continue;
920a13144ffSStefano Zampini 
921a13144ffSStefano Zampini     /* import extended row */
922a13144ffSStefano Zampini     mark--;
923a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
924a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
925a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
926a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
927a13144ffSStefano Zampini     extrowcum[mark] += size;
928a13144ffSStefano Zampini   }
929a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
930a13144ffSStefano Zampini   cum  = 0;
931a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
932a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
933a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
934a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
935a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
936a13144ffSStefano Zampini   }
937a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
938a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
939a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
940a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
941a13144ffSStefano Zampini 
942a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
943a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
944a13144ffSStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
945a13144ffSStefano Zampini   for (i=0;i<maxsize;i++) vals[i] = 1.;
946a13144ffSStefano Zampini 
947a13144ffSStefano Zampini   /* Create vectors for quadrature rules */
948c2151214SStefano Zampini   /* TODO preserve other quadratures */
949a13144ffSStefano Zampini   ierr = PetscMalloc1(nquads,&quads);CHKERRQ(ierr);
950a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
951a13144ffSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quads[i],NULL);CHKERRQ(ierr);
952a13144ffSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quads[i],el2g);CHKERRQ(ierr);
953a13144ffSStefano Zampini   }
954a13144ffSStefano Zampini   ierr = PCBDDCNullSpaceCreate(comm,PETSC_FALSE,nquads,quads,&nnsp);CHKERRQ(ierr);
955a13144ffSStefano Zampini 
956a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
957a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
958c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
959c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
960a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
961a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
962a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
963a13144ffSStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,el2g,el2g);CHKERRQ(ierr);
964a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
965a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
966a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
967a13144ffSStefano Zampini 
968a13144ffSStefano Zampini   /* Defaults to identity */
969c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
970a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
971a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
972a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
973a13144ffSStefano Zampini 
974a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
975a13144ffSStefano Zampini     Mat Gins = NULL, GKins = NULL;
976a13144ffSStefano Zampini 
977a13144ffSStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],&Gins,&GKins,work,rwork);CHKERRQ(ierr);
978a13144ffSStefano Zampini     if (Gins && GKins) {
979a13144ffSStefano Zampini       PetscScalar    *data;
980a13144ffSStefano Zampini       const PetscInt *rows,*cols;
981a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
982a13144ffSStefano Zampini 
983a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
984a13144ffSStefano Zampini       /* H1 */
985a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
986a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
987a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
988a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
989a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
990a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
991a13144ffSStefano Zampini       /* complement */
992a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
993a13144ffSStefano Zampini       if (ncc > nquads-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet supported ncc %d nquads %d",ncc,nquads);
994a13144ffSStefano 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);
995a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
996a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
997a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
998a13144ffSStefano Zampini       /* Gins kernel quadratures */
999a13144ffSStefano Zampini       for (j=0;j<ncc;j++) {
1000a13144ffSStefano Zampini         ierr = VecSetValueLocal(quads[j],cols[nch+j],1.,INSERT_VALUES);CHKERRQ(ierr);
1001a13144ffSStefano Zampini       }
1002a13144ffSStefano Zampini       /* H1 average */
1003a13144ffSStefano Zampini       ierr = VecSetValuesLocal(quads[nquads-1],nch,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1004a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
1005a13144ffSStefano Zampini     }
1006a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
1007a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
1008a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
1009a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
1010a13144ffSStefano Zampini   }
1011a13144ffSStefano Zampini 
1012a13144ffSStefano Zampini   /* Start assembling */
1013a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1014a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1015a13144ffSStefano Zampini     ierr = VecAssemblyBegin(quads[i]);CHKERRQ(ierr);
1016a13144ffSStefano Zampini   }
1017a13144ffSStefano Zampini 
1018a13144ffSStefano Zampini   /* Free */
1019c2151214SStefano Zampini   if (fl2g) {
1020c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
1021c2151214SStefano Zampini     for (i=0;i<nee;i++) {
1022c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
1023c2151214SStefano Zampini     }
1024c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
1025c2151214SStefano Zampini   }
1026c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
1027c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1028c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
1029a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
1030a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
1031c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
1032c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
1033a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
1034a13144ffSStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1035a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
1036a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
1037a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
1038a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
1039a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1040a13144ffSStefano Zampini 
1041a13144ffSStefano Zampini   /* Complete assembling */
1042a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1043a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1044a13144ffSStefano Zampini     ierr = VecAssemblyEnd(quads[i]);CHKERRQ(ierr);
1045a13144ffSStefano Zampini   }
1046a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1047a13144ffSStefano Zampini     ierr = VecDestroy(&quads[i]);CHKERRQ(ierr);
1048a13144ffSStefano Zampini   }
1049a13144ffSStefano Zampini   ierr = PetscFree(quads);CHKERRQ(ierr);
1050a13144ffSStefano Zampini 
1051a13144ffSStefano Zampini   /* set change of basis */
1052a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
1053a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1054a13144ffSStefano Zampini 
1055a13144ffSStefano Zampini   /* set quadratures */
1056a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
1057a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
1058a13144ffSStefano Zampini 
1059a13144ffSStefano Zampini   PetscFunctionReturn(0);
1060a13144ffSStefano Zampini }
1061a13144ffSStefano Zampini 
1062d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1063d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1064d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1065d8203eabSStefano Zampini #undef __FUNCT__
1066d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1067d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1068d8203eabSStefano Zampini {
1069d8203eabSStefano Zampini   PetscErrorCode ierr;
1070d8203eabSStefano Zampini   PetscInt       i;
1071d8203eabSStefano Zampini 
1072d8203eabSStefano Zampini   PetscFunctionBegin;
1073d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1074d8203eabSStefano Zampini     PetscInt first,last;
1075d8203eabSStefano Zampini 
1076d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
107786fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1078d8203eabSStefano Zampini     if (i>=first && i < last) {
1079d8203eabSStefano Zampini       PetscScalar *data;
1080d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1081d8203eabSStefano Zampini       if (!has_const) {
1082d8203eabSStefano Zampini         data[i-first] = 1.;
1083d8203eabSStefano Zampini       } else {
108486fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
108586fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1086d8203eabSStefano Zampini       }
1087d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1088d8203eabSStefano Zampini     }
1089d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1090d8203eabSStefano Zampini   }
1091d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1092d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1093d8203eabSStefano Zampini     PetscInt first,last;
1094d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1095d8203eabSStefano Zampini     if (i>=first && i < last) {
1096d8203eabSStefano Zampini       PetscScalar *data;
1097d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1098d8203eabSStefano Zampini       if (!has_const) {
1099d8203eabSStefano Zampini         data[i-first] = 0.;
1100d8203eabSStefano Zampini       } else {
110186fa73c5SStefano Zampini         data[2*i-first] = 0.;
110286fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1103d8203eabSStefano Zampini       }
1104d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1105d8203eabSStefano Zampini     }
1106d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1107d8203eabSStefano Zampini   }
1108d8203eabSStefano Zampini   PetscFunctionReturn(0);
1109d8203eabSStefano Zampini }
1110d8203eabSStefano Zampini 
1111669cc0f4SStefano Zampini #undef __FUNCT__
1112669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
11138ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1114669cc0f4SStefano Zampini {
1115a198735bSStefano Zampini   Mat                    loc_divudotp;
1116fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
11178ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1118669cc0f4SStefano Zampini   IS                     *faces,*edges;
1119669cc0f4SStefano Zampini   PetscScalar            *vals;
1120669cc0f4SStefano Zampini   const PetscScalar      *array;
1121669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
11221ae86dd6SStefano Zampini   PetscMPIInt            rank;
1123a198735bSStefano Zampini   PetscErrorCode         ierr;
1124669cc0f4SStefano Zampini 
1125669cc0f4SStefano Zampini   PetscFunctionBegin;
1126669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1127669cc0f4SStefano Zampini   if (graph->twodim) {
1128669cc0f4SStefano Zampini     lmaxneighs = 2;
1129669cc0f4SStefano Zampini   } else {
1130669cc0f4SStefano Zampini     lmaxneighs = 1;
1131669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1132669cc0f4SStefano Zampini       const PetscInt *idxs;
1133669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1134669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1135669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1136669cc0f4SStefano Zampini     }
1137669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1138669cc0f4SStefano Zampini   }
1139669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1140669cc0f4SStefano Zampini   maxsize = 0;
1141669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1142669cc0f4SStefano Zampini     PetscInt nn;
1143669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1144669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1145669cc0f4SStefano Zampini   }
1146669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1147669cc0f4SStefano Zampini     PetscInt nn;
1148669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1149669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1150669cc0f4SStefano Zampini   }
1151669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1152669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1153669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
11548ae0ca82SStefano Zampini   if (!transpose) {
11558ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
11568ae0ca82SStefano Zampini   } else {
11578ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
11588ae0ca82SStefano Zampini   }
1159669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
11601ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1161d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1162669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
11638ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1164669cc0f4SStefano Zampini   }
1165d8203eabSStefano Zampini 
1166669cc0f4SStefano Zampini   /* compute local quad vec */
1167a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
11688ae0ca82SStefano Zampini   if (!transpose) {
1169a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
11708ae0ca82SStefano Zampini   } else {
11718ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
11728ae0ca82SStefano Zampini   }
1173669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
11748ae0ca82SStefano Zampini   if (!transpose) {
1175a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
11768ae0ca82SStefano Zampini   } else {
11778ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
11788ae0ca82SStefano Zampini   }
1179fa23a32eSStefano Zampini   if (vl2l) {
1180fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1181fa23a32eSStefano Zampini   } else {
1182fa23a32eSStefano Zampini     vins = v;
1183fa23a32eSStefano Zampini   }
1184fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1185669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
11869a962809SStefano Zampini 
11871ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
11881ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1189669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1190669cc0f4SStefano Zampini     const PetscInt    *idxs;
1191669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1192669cc0f4SStefano Zampini 
1193669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1194669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1195669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
11961ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1197669cc0f4SStefano Zampini     idx = -(idx+1);
1198669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1199669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1200669cc0f4SStefano Zampini   }
1201669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1202669cc0f4SStefano Zampini     const PetscInt    *idxs;
1203669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1204669cc0f4SStefano Zampini 
1205669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1206669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1207669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
12081ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1209669cc0f4SStefano Zampini     idx = -(idx+1);
1210669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1211669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1212669cc0f4SStefano Zampini   }
1213c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1214fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1215fa23a32eSStefano Zampini   if (vl2l) {
1216fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1217fa23a32eSStefano Zampini   }
1218669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1219669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1220669cc0f4SStefano Zampini 
1221669cc0f4SStefano Zampini   /* assemble near null space */
1222669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1223669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1224669cc0f4SStefano Zampini   }
1225669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1226669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1227669cc0f4SStefano Zampini   }
1228669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1229669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1230669cc0f4SStefano Zampini }
1231669cc0f4SStefano Zampini 
1232669cc0f4SStefano Zampini 
1233a3df083aSStefano Zampini #undef __FUNCT__
12341f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
12351f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
12361f4df5f7SStefano Zampini {
12371f4df5f7SStefano Zampini   PetscErrorCode ierr;
12381f4df5f7SStefano Zampini   Vec            local,global;
12391f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12401f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
12411f4df5f7SStefano Zampini 
12421f4df5f7SStefano Zampini   PetscFunctionBegin;
12431f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
12441f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
12451f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
12461f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
12471f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
12481f4df5f7SStefano Zampini       PetscInt i;
12491f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12501f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
12511f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12521f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12531f4df5f7SStefano Zampini       }
12541f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
12551f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
12561f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
12571f4df5f7SStefano Zampini     }
12581f4df5f7SStefano Zampini   } else {
1259986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
12601f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1261986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1262986cdee1SStefano Zampini       if (i > 1) {
1263986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
12641f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12651f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12661f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12671f4df5f7SStefano Zampini         }
12681f4df5f7SStefano Zampini       }
12691f4df5f7SStefano Zampini     }
1270986cdee1SStefano Zampini   }
12711f4df5f7SStefano Zampini 
12721f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
12731f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
12741f4df5f7SStefano Zampini   }
12751f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
12761f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
12771f4df5f7SStefano Zampini   }
12781f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
12791f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
12801f4df5f7SStefano Zampini   }
12811f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
12821f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
12831f4df5f7SStefano Zampini   PetscFunctionReturn(0);
12841f4df5f7SStefano Zampini }
12851f4df5f7SStefano Zampini 
12861f4df5f7SStefano Zampini #undef __FUNCT__
12873e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
12883e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
12893e589ea0SStefano Zampini {
12903e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
12913e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
12923e589ea0SStefano Zampini   PetscErrorCode    ierr;
12933e589ea0SStefano Zampini 
12943e589ea0SStefano Zampini   PetscFunctionBegin;
12953e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
12963e589ea0SStefano Zampini     PetscFunctionReturn(0);
12973e589ea0SStefano Zampini   }
12983e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
12993e589ea0SStefano Zampini     Vec swap;
13003e589ea0SStefano Zampini 
13013e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
13023e589ea0SStefano Zampini     swap = pcbddc->work_change;
13033e589ea0SStefano Zampini     pcbddc->work_change = r;
13043e589ea0SStefano Zampini     r = swap;
13053e589ea0SStefano Zampini   }
13063e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13073e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13083e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13093e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
13103e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13113e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13123e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
13133e589ea0SStefano Zampini     Vec swap;
13143e589ea0SStefano Zampini 
13153e589ea0SStefano Zampini     swap = r;
13163e589ea0SStefano Zampini     r = pcbddc->work_change;
13173e589ea0SStefano Zampini     pcbddc->work_change = swap;
13183e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
13193e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
13203e589ea0SStefano Zampini   }
13213e589ea0SStefano Zampini   PetscFunctionReturn(0);
13223e589ea0SStefano Zampini }
13233e589ea0SStefano Zampini 
13243e589ea0SStefano Zampini #undef __FUNCT__
1325a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1326a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1327a3df083aSStefano Zampini {
1328a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1329a3df083aSStefano Zampini   PetscErrorCode          ierr;
1330a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1331a3df083aSStefano Zampini 
1332a3df083aSStefano Zampini   PetscFunctionBegin;
1333a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1334a3df083aSStefano Zampini   if (transpose) {
1335a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1336a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1337a3df083aSStefano Zampini   } else {
1338a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1339a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1340a3df083aSStefano Zampini   }
1341a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1342a3df083aSStefano Zampini   if (apply_right) {
1343a3df083aSStefano Zampini     const PetscScalar *ax;
1344a3df083aSStefano Zampini     PetscInt          nl,i;
1345a3df083aSStefano Zampini 
1346a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1347a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1348a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1349a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1350a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1351a3df083aSStefano Zampini       PetscScalar    sum,val;
1352a3df083aSStefano Zampini       const PetscInt *idxs;
1353a3df083aSStefano Zampini       PetscInt       nz,j;
1354a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1355a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1356a3df083aSStefano Zampini       sum = 0.;
1357a3df083aSStefano Zampini       if (ctx->apply_p0) {
1358a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1359a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1360a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1361a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1362a3df083aSStefano Zampini         }
1363a3df083aSStefano Zampini       } else {
1364a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1365a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1366a3df083aSStefano Zampini         }
1367a3df083aSStefano Zampini       }
1368a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1369a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1370a3df083aSStefano Zampini     }
1371a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1372a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1373a3df083aSStefano Zampini   }
1374a3df083aSStefano Zampini   if (transpose) {
1375a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1376a3df083aSStefano Zampini   } else {
1377a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1378a3df083aSStefano Zampini   }
1379a3df083aSStefano Zampini   if (reset_x) {
1380a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1381a3df083aSStefano Zampini   }
1382a3df083aSStefano Zampini   if (apply_left) {
1383a3df083aSStefano Zampini     PetscScalar *ay;
1384a3df083aSStefano Zampini     PetscInt    i;
1385a3df083aSStefano Zampini 
1386a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1387a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1388a3df083aSStefano Zampini       PetscScalar    sum,val;
1389a3df083aSStefano Zampini       const PetscInt *idxs;
1390a3df083aSStefano Zampini       PetscInt       nz,j;
1391a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1392a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1393a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1394a3df083aSStefano Zampini       if (ctx->apply_p0) {
1395a3df083aSStefano Zampini         sum = 0.;
1396a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1397a3df083aSStefano Zampini           sum += ay[idxs[j]];
1398a3df083aSStefano Zampini           ay[idxs[j]] += val;
1399a3df083aSStefano Zampini         }
1400a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1401a3df083aSStefano Zampini       } else {
1402a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1403a3df083aSStefano Zampini           ay[idxs[j]] += val;
1404a3df083aSStefano Zampini         }
1405a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1406a3df083aSStefano Zampini       }
1407a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1408a3df083aSStefano Zampini     }
1409a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1410a3df083aSStefano Zampini   }
1411a3df083aSStefano Zampini   PetscFunctionReturn(0);
1412a3df083aSStefano Zampini }
1413a3df083aSStefano Zampini 
1414a3df083aSStefano Zampini #undef __FUNCT__
1415a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1416a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1417a3df083aSStefano Zampini {
1418a3df083aSStefano Zampini   PetscErrorCode ierr;
1419a3df083aSStefano Zampini 
1420a3df083aSStefano Zampini   PetscFunctionBegin;
1421a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1422a3df083aSStefano Zampini   PetscFunctionReturn(0);
1423a3df083aSStefano Zampini }
1424a3df083aSStefano Zampini 
1425a3df083aSStefano Zampini #undef __FUNCT__
1426a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1427a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1428a3df083aSStefano Zampini {
1429a3df083aSStefano Zampini   PetscErrorCode ierr;
1430a3df083aSStefano Zampini 
1431a3df083aSStefano Zampini   PetscFunctionBegin;
1432a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1433a3df083aSStefano Zampini   PetscFunctionReturn(0);
1434a3df083aSStefano Zampini }
1435a3df083aSStefano Zampini 
1436a3df083aSStefano Zampini #undef __FUNCT__
1437a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1438a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1439a3df083aSStefano Zampini {
1440a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1441a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1442a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1443a3df083aSStefano Zampini   PetscErrorCode          ierr;
1444a3df083aSStefano Zampini 
1445a3df083aSStefano Zampini   PetscFunctionBegin;
1446a3df083aSStefano Zampini   if (!restore) {
14471dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1448a3df083aSStefano Zampini     PetscScalar        *work;
1449b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1450a3df083aSStefano Zampini 
14519a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
14529a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1453a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1454a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1455a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1456a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1457a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1458a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1459a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1460a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1461a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1462a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1463a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1464a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1465059032f7SStefano Zampini     if (reuse) {
1466a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
14671dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1468059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1469059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1470059032f7SStefano Zampini       PetscInt               i;
1471059032f7SStefano Zampini 
1472059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1473059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1474059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1475059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1476059032f7SStefano Zampini       }
1477059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
14781dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1479059032f7SStefano Zampini     }
1480a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1481a3df083aSStefano Zampini     ctx->work = work;
1482a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1483a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1484a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1485a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1486a3df083aSStefano Zampini 
1487a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1488a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1489a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1490a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1491a3df083aSStefano Zampini   } else {
14921dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
14931dd7afcfSStefano Zampini       PetscFunctionReturn(0);
14941dd7afcfSStefano Zampini     }
1495a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1496a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1497a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
14981dd7afcfSStefano Zampini     ctx->A = NULL;
14991dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
15001dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
15011dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
15021dd7afcfSStefano Zampini     if (ctx->free) {
1503059032f7SStefano Zampini       PetscInt i;
15041dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1505059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1506059032f7SStefano Zampini       }
1507059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1508059032f7SStefano Zampini     }
1509a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1510a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1511a3df083aSStefano Zampini   }
1512a3df083aSStefano Zampini   PetscFunctionReturn(0);
1513a3df083aSStefano Zampini }
1514a3df083aSStefano Zampini 
1515a3df083aSStefano Zampini /* used just in bddc debug mode */
1516a3df083aSStefano Zampini #undef __FUNCT__
1517a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1518a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1519a3df083aSStefano Zampini {
1520a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1521a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1522a3df083aSStefano Zampini   Mat            An;
1523a3df083aSStefano Zampini   PetscErrorCode ierr;
1524a3df083aSStefano Zampini 
1525a3df083aSStefano Zampini   PetscFunctionBegin;
1526a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1527a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1528a3df083aSStefano Zampini   if (is1) {
1529a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1530a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1531a3df083aSStefano Zampini   } else {
1532a3df083aSStefano Zampini     *B = An;
1533a3df083aSStefano Zampini   }
1534a3df083aSStefano Zampini   PetscFunctionReturn(0);
1535a3df083aSStefano Zampini }
1536a3df083aSStefano Zampini 
15371cf9b237SStefano Zampini /* TODO: add reuse flag */
15381cf9b237SStefano Zampini #undef __FUNCT__
15391cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
15401cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
15411cf9b237SStefano Zampini {
15421cf9b237SStefano Zampini   Mat            Bt;
15431cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
15441cf9b237SStefano Zampini   const PetscInt *ii,*ij;
15451cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
15461cf9b237SStefano Zampini   PetscBool      flg_row;
15471cf9b237SStefano Zampini   PetscErrorCode ierr;
15481cf9b237SStefano Zampini 
15491cf9b237SStefano Zampini   PetscFunctionBegin;
15501cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
15511cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15521cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
15531cf9b237SStefano Zampini   nnz = n;
15541cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
15551cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
15561cf9b237SStefano Zampini   }
15571cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
15581cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
15591cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
15601cf9b237SStefano Zampini   nnz = 0;
15611cf9b237SStefano Zampini   bii[0] = 0;
15621cf9b237SStefano Zampini   for (i=0;i<n;i++) {
15631cf9b237SStefano Zampini     PetscInt j;
15641cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
15651cf9b237SStefano Zampini       PetscScalar entry = a[j];
15661cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
15671cf9b237SStefano Zampini         bij[nnz] = ij[j];
15681cf9b237SStefano Zampini         bdata[nnz] = entry;
15691cf9b237SStefano Zampini         nnz++;
15701cf9b237SStefano Zampini       }
15711cf9b237SStefano Zampini     }
15721cf9b237SStefano Zampini     bii[i+1] = nnz;
15731cf9b237SStefano Zampini   }
15741cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
15751cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
15761cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15771cf9b237SStefano Zampini   {
15781cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
15791cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
15801cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
15811cf9b237SStefano Zampini   }
15821cf9b237SStefano Zampini   *B = Bt;
15831cf9b237SStefano Zampini   PetscFunctionReturn(0);
15841cf9b237SStefano Zampini }
15851cf9b237SStefano Zampini 
1586674ae819SStefano Zampini #undef __FUNCT__
15874f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
15884f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
15894f1b2e48SStefano Zampini {
15904f1b2e48SStefano Zampini   Mat                    B;
15914f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
15924f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
15934f1b2e48SStefano Zampini   PCBDDCGraph            graph;
15944f1b2e48SStefano Zampini   PetscInt               i,n;
15954f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
15964f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
15974f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
15984f1b2e48SStefano Zampini   PetscErrorCode         ierr;
15994f1b2e48SStefano Zampini 
16004f1b2e48SStefano Zampini   PetscFunctionBegin;
160163c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
160263c961adSStefano Zampini     *ncc = 0;
160363c961adSStefano Zampini     *cc = NULL;
160463c961adSStefano Zampini     PetscFunctionReturn(0);
160563c961adSStefano Zampini   }
16064f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
16074f1b2e48SStefano Zampini   if (!isseqaij && filter) {
16081cf9b237SStefano Zampini     PetscBool isseqdense;
16091cf9b237SStefano Zampini 
16101cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
16111cf9b237SStefano Zampini     if (!isseqdense) {
16124f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
16131cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
16141cf9b237SStefano Zampini       PetscScalar *array;
16151cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
16161cf9b237SStefano Zampini 
16171cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
16181cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
16191cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
16201cf9b237SStefano Zampini       for (i=0;i<n;i++) {
16211cf9b237SStefano Zampini         PetscInt j;
16221cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
16231cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
16241cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
16251cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
16261cf9b237SStefano Zampini         }
16271cf9b237SStefano Zampini       }
16281cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
16299d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
16301cf9b237SStefano Zampini     }
16314f1b2e48SStefano Zampini   } else {
16324f1b2e48SStefano Zampini     B = A;
16334f1b2e48SStefano Zampini   }
16344f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16354f1b2e48SStefano Zampini 
16364f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
16374f1b2e48SStefano Zampini   if (filter) {
16384f1b2e48SStefano Zampini     PetscScalar *data;
16394f1b2e48SStefano Zampini     PetscInt    j,cum;
16404f1b2e48SStefano Zampini 
16414f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
16424f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
16434f1b2e48SStefano Zampini     cum = 0;
16444f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
16454f1b2e48SStefano Zampini       PetscInt t;
16464f1b2e48SStefano Zampini 
16474f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
16484f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
16494f1b2e48SStefano Zampini           continue;
16504f1b2e48SStefano Zampini         }
16514f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
16524f1b2e48SStefano Zampini       }
16534f1b2e48SStefano Zampini       t = xadj_filtered[i];
16544f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
16554f1b2e48SStefano Zampini       cum += t;
16564f1b2e48SStefano Zampini     }
16574f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
16584f1b2e48SStefano Zampini   } else {
16594f1b2e48SStefano Zampini     xadj_filtered = NULL;
16604f1b2e48SStefano Zampini     adjncy_filtered = NULL;
16614f1b2e48SStefano Zampini   }
16624f1b2e48SStefano Zampini 
16634f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
16644f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
16654f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
16664f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
16674f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1668be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
16694f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
16704f1b2e48SStefano Zampini   if (xadj_filtered) {
16714f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
16724f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
16734f1b2e48SStefano Zampini   } else {
16744f1b2e48SStefano Zampini     graph->xadj = xadj;
16754f1b2e48SStefano Zampini     graph->adjncy = adjncy;
16764f1b2e48SStefano Zampini   }
16774f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
16784f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
16794f1b2e48SStefano Zampini   /* partial clean up */
16804f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
16814f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16821cf9b237SStefano Zampini   if (A != B) {
16834f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
16844f1b2e48SStefano Zampini   }
16854f1b2e48SStefano Zampini 
16864f1b2e48SStefano Zampini   /* get back data */
16871cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
16881cf9b237SStefano Zampini   if (cc) {
16894f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
16904f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
16914f1b2e48SStefano 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);
16924f1b2e48SStefano Zampini     }
16934f1b2e48SStefano Zampini     *cc = cc_n;
16941cf9b237SStefano Zampini   }
16954f1b2e48SStefano Zampini   /* clean up graph */
16964f1b2e48SStefano Zampini   graph->xadj = 0;
16974f1b2e48SStefano Zampini   graph->adjncy = 0;
16984f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
16994f1b2e48SStefano Zampini   PetscFunctionReturn(0);
17004f1b2e48SStefano Zampini }
17014f1b2e48SStefano Zampini 
17024f1b2e48SStefano Zampini #undef __FUNCT__
17035408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
17045408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
17055408967cSStefano Zampini {
17065408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17075408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1708dee84bffSStefano Zampini   IS             dirIS = NULL;
17094f1b2e48SStefano Zampini   PetscInt       i;
17105408967cSStefano Zampini   PetscErrorCode ierr;
17115408967cSStefano Zampini 
17125408967cSStefano Zampini   PetscFunctionBegin;
1713dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
17145408967cSStefano Zampini   if (zerodiag) {
17155408967cSStefano Zampini     Mat            A;
17165408967cSStefano Zampini     Vec            vec3_N;
17175408967cSStefano Zampini     PetscScalar    *vals;
17185408967cSStefano Zampini     const PetscInt *idxs;
1719d12d3064SStefano Zampini     PetscInt       nz,*count;
17205408967cSStefano Zampini 
17215408967cSStefano Zampini     /* p0 */
17225408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
17235408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
17245408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17255408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17264f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
17275408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17285408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
17295408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
17305408967cSStefano Zampini     /* v_I */
17315408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
17325408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
17335408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17345408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
17355408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17365408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
17375408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17385408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17395408967cSStefano Zampini     if (dirIS) {
17405408967cSStefano Zampini       PetscInt n;
17415408967cSStefano Zampini 
17425408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
17435408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
17445408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
17455408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17465408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
17475408967cSStefano Zampini     }
17485408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
17495408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
17505408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
17515408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1752669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
17535408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
17545408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
17559a962809SStefano 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]));
17565408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
17575408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1758d12d3064SStefano Zampini 
1759d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1760d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1761d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1762d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1763d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1764d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17659a962809SStefano 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]);
1766d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1767d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
17685408967cSStefano Zampini   }
1769dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
17705408967cSStefano Zampini 
17715408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
17725408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
17734f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
17745408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
17754f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
17765408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1777f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1778f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1779f2a566d8SStefano 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);
1780f2a566d8SStefano Zampini   }
17815408967cSStefano Zampini   PetscFunctionReturn(0);
17825408967cSStefano Zampini }
17835408967cSStefano Zampini 
17845408967cSStefano Zampini #undef __FUNCT__
1785339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1786339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1787339f8db1SStefano Zampini {
1788339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17894f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1790b0f5fe93SStefano Zampini   PetscInt       nz,n;
17911f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
17924f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1793339f8db1SStefano Zampini   PetscErrorCode ierr;
1794339f8db1SStefano Zampini 
1795339f8db1SStefano Zampini   PetscFunctionBegin;
17969f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
17979f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1798a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1799a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1800a3df083aSStefano Zampini   }
1801a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1802a3df083aSStefano Zampini   pcbddc->benign_n = 0;
18031ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
18044f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
18054f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
18064f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
18071ae86dd6SStefano Zampini      since the local Schur complements are already SPD
18084f1b2e48SStefano Zampini   */
18094f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
18104f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
181140fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
18124f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
18134f1b2e48SStefano Zampini 
18144f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
18154f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
18164f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
18174f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1818ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
181940fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
182040fa8d13SStefano Zampini     if (!sorted) {
182140fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
182240fa8d13SStefano Zampini     }
182340fa8d13SStefano Zampini   } else {
182440fa8d13SStefano Zampini     pressures = NULL;
182540fa8d13SStefano Zampini   }
182697d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
182797d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
182827b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
182997d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1830339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1831339f8db1SStefano Zampini   if (!sorted) {
1832339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1833339f8db1SStefano Zampini   }
1834339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
18354f1b2e48SStefano Zampini   if (!nz) {
18364f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
18374f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
183840fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
183940fa8d13SStefano Zampini   }
18404f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
18414f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
18424f1b2e48SStefano Zampini   zerodiag_subs = NULL;
18434f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
18441f4df5f7SStefano Zampini   n_interior_dofs = 0;
18451f4df5f7SStefano Zampini   interior_dofs = NULL;
18461f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
18471f4df5f7SStefano Zampini     PetscInt n,i,j;
18481f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
18491f4df5f7SStefano Zampini     PetscInt *iwork;
18501f4df5f7SStefano Zampini 
18511f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
18521f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18531f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
18541f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
185590648384SStefano Zampini     for (i=1;i<n_neigh;i++)
18561f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
18571f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
18581f4df5f7SStefano Zampini     for (i=0;i<n;i++)
18591f4df5f7SStefano Zampini       if (!iwork[i])
18601f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
18611f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
18621f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18631f4df5f7SStefano Zampini   }
18644f1b2e48SStefano Zampini   if (has_null_pressures) {
18654f1b2e48SStefano Zampini     IS             *subs;
18661f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
18671f4df5f7SStefano Zampini     const PetscInt *idxs;
18681f4df5f7SStefano Zampini     PetscScalar    *array;
18691f4df5f7SStefano Zampini     Vec            *work;
18701f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
18714f1b2e48SStefano Zampini 
18724f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
18734f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
18741f4df5f7SStefano 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) */
18751f4df5f7SStefano Zampini     if (pcbddc->current_level) {
18761f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
18771f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
18781f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
18791f4df5f7SStefano Zampini       /* work[0] = 1_p */
18801f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
18811f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
18821f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
18831f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
18841f4df5f7SStefano Zampini       /* work[0] = 1_v */
18851f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
18861f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
18871f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
18881f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
18891f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
18901f4df5f7SStefano Zampini     }
18914f1b2e48SStefano Zampini     if (nsubs > 1) {
18924f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
18934f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
18944f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
18954f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
18964f1b2e48SStefano Zampini         PetscInt               nl;
18974f1b2e48SStefano Zampini 
18984f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
18994f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
19004f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
19014f1b2e48SStefano Zampini         if (nl) {
19024f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
19034f1b2e48SStefano Zampini 
19041f4df5f7SStefano Zampini           if (pcbddc->current_level) {
19051f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
19061f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
19071f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
19081f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19091f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
19101f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19111f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
19121f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
19131f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
19141f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
19151f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
19161f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
19171f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19181f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
19191f4df5f7SStefano Zampini                 break;
19201f4df5f7SStefano Zampini               }
19211f4df5f7SStefano Zampini             }
19221f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
19231f4df5f7SStefano Zampini           }
19241f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
19251f4df5f7SStefano Zampini             IS       t_bc;
19261f4df5f7SStefano Zampini             PetscInt nzb;
19271f4df5f7SStefano Zampini 
19281f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
19291f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
19301f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
19311f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
19321f4df5f7SStefano Zampini           }
19331f4df5f7SStefano Zampini           if (valid && pressures) {
19344f1b2e48SStefano Zampini             IS t_pressure_subs;
19354f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
19364f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
19374f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
19384f1b2e48SStefano Zampini           }
19394f1b2e48SStefano Zampini           if (valid) {
19404f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
19414f1b2e48SStefano Zampini             pcbddc->benign_n++;
19424f1b2e48SStefano Zampini           } else {
19434f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
19444f1b2e48SStefano Zampini           }
19454f1b2e48SStefano Zampini         }
19464f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
19474f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
19484f1b2e48SStefano Zampini       }
19494f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
19504f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
19511f4df5f7SStefano Zampini 
19521f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
19531f4df5f7SStefano Zampini         PetscInt nzb;
19541f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
19551f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
19561f4df5f7SStefano Zampini       }
19571f4df5f7SStefano Zampini       if (valid && pressures) {
19584f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
19594f1b2e48SStefano Zampini       }
19601f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
19611f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
19621f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
19631f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19641f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
19651f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19661f4df5f7SStefano Zampini               valid = PETSC_FALSE;
19671f4df5f7SStefano Zampini               break;
19681f4df5f7SStefano Zampini           }
19691f4df5f7SStefano Zampini         }
19701f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19711f4df5f7SStefano Zampini       }
19724f1b2e48SStefano Zampini       if (valid) {
19734f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1974ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
19754f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
19764f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
19774f1b2e48SStefano Zampini       }
19784f1b2e48SStefano Zampini     }
19791f4df5f7SStefano Zampini     if (pcbddc->current_level) {
19801f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
19814f1b2e48SStefano Zampini     }
19821f4df5f7SStefano Zampini   }
19831f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
19844f1b2e48SStefano Zampini 
19854f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1986b9b0e38cSStefano Zampini     PetscInt n;
1987b9b0e38cSStefano Zampini 
19884f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
19894f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1990b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1991b9b0e38cSStefano Zampini     if (n) {
19924f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
19934f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
19944f1b2e48SStefano Zampini     }
1995b9b0e38cSStefano Zampini   }
19964f1b2e48SStefano Zampini 
19974f1b2e48SStefano Zampini   /* final check for null pressures */
19984f1b2e48SStefano Zampini   if (zerodiag && pressures) {
19994f1b2e48SStefano Zampini     PetscInt nz,np;
20004f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
20014f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
20024f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
20034f1b2e48SStefano Zampini   }
20044f1b2e48SStefano Zampini 
20054f1b2e48SStefano Zampini   if (recompute_zerodiag) {
20064f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
20074f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
20084f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
20094f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
20104f1b2e48SStefano Zampini     } else {
20114f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
20124f1b2e48SStefano Zampini 
20134f1b2e48SStefano Zampini       nzn = 0;
20144f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20154f1b2e48SStefano Zampini         PetscInt ns;
20164f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20174f1b2e48SStefano Zampini         nzn += ns;
20184f1b2e48SStefano Zampini       }
20194f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
20204f1b2e48SStefano Zampini       nzn = 0;
20214f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20224f1b2e48SStefano Zampini         PetscInt ns,*idxs;
20234f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20244f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20254f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
20264f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20274f1b2e48SStefano Zampini         nzn += ns;
20284f1b2e48SStefano Zampini       }
20294f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
20304f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
20314f1b2e48SStefano Zampini     }
20324f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
20334f1b2e48SStefano Zampini   }
20344f1b2e48SStefano Zampini 
2035669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2036a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2037a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2038a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2039a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2040a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2041a198735bSStefano Zampini 
20421f4df5f7SStefano Zampini     if (pressures) {
20431f4df5f7SStefano Zampini       isused = pressures;
20441f4df5f7SStefano Zampini     } else {
20451f4df5f7SStefano Zampini       isused = zerodiag;
20461f4df5f7SStefano Zampini     }
2047a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2048669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
20491ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
20501ae86dd6SStefano 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");
2051a198735bSStefano Zampini     n_isused = 0;
2052a198735bSStefano Zampini     if (isused) {
2053a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2054a198735bSStefano Zampini     }
2055a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2056a198735bSStefano Zampini     st = st-n_isused;
20571ae86dd6SStefano Zampini     if (n) {
2058a198735bSStefano Zampini       const PetscInt *gidxs;
2059a198735bSStefano Zampini 
2060a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2061a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2062a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2063a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2064a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2065a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
20661ae86dd6SStefano Zampini     } else {
2067a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2068a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2069a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2070a198735bSStefano Zampini     }
2071a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2072a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2073a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2074a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2075a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2076a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2077a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2078a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2079a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2080a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2081a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2082a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2083a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2084a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
20851ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20861ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20871ae86dd6SStefano Zampini   }
2088b3afcdbeSStefano Zampini 
2089b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
20904f1b2e48SStefano Zampini   if (has_null_pressures) {
20914f1b2e48SStefano Zampini     IS             zerodiagc;
20924f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
20934f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
20944f1b2e48SStefano Zampini 
20954f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2096339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2097339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2098339f8db1SStefano Zampini     /* local change of basis for pressures */
2099339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
210097d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2101339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2102339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2103339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
21044f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
21054f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
21064f1b2e48SStefano Zampini       PetscInt nzs,j;
21074f1b2e48SStefano Zampini 
21084f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
21094f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21104f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
21114f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
21124f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21134f1b2e48SStefano Zampini     }
2114339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2115339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2116339f8db1SStefano Zampini     /* set identity on velocities */
2117339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2118339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2119339f8db1SStefano Zampini     }
21204f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
21214f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
21229f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
21234f1b2e48SStefano 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);
2124339f8db1SStefano Zampini     /* set change on pressures */
21254f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
21264f1b2e48SStefano Zampini       PetscScalar *array;
21274f1b2e48SStefano Zampini       PetscInt    nzs;
21284f1b2e48SStefano Zampini 
21294f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
21304f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
21314f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2132339f8db1SStefano Zampini         PetscScalar vals[2];
2133339f8db1SStefano Zampini         PetscInt    cols[2];
2134339f8db1SStefano Zampini 
2135339f8db1SStefano Zampini         cols[0] = idxs[i];
21364f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2137339f8db1SStefano Zampini         vals[0] = 1.;
2138b0f5fe93SStefano Zampini         vals[1] = 1.;
21394f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2140339f8db1SStefano Zampini       }
21414f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
21424f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
21434f1b2e48SStefano Zampini       array[nzs-1] = 1.;
21444f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
21454f1b2e48SStefano Zampini       /* store local idxs for p0 */
21464f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
21474f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2148339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
21494f1b2e48SStefano Zampini     }
2150339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2151339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2152a3df083aSStefano Zampini     /* project if needed */
2153a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
21541dd7afcfSStefano Zampini       Mat M;
21551dd7afcfSStefano Zampini 
21561dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2157339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
21581dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
21591dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2160a3df083aSStefano Zampini     }
21614f1b2e48SStefano Zampini     /* store global idxs for p0 */
21624f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2163339f8db1SStefano Zampini   }
2164ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
21654f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2166b0f5fe93SStefano Zampini 
2167b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2168b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
216927b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
217027b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2171339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2172339f8db1SStefano Zampini   PetscFunctionReturn(0);
2173339f8db1SStefano Zampini }
2174339f8db1SStefano Zampini 
2175339f8db1SStefano Zampini #undef __FUNCT__
2176015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2177015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2178efc2fbd9SStefano Zampini {
2179efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2180de9d7bd0SStefano Zampini   PetscScalar    *array;
2181efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2182efc2fbd9SStefano Zampini 
2183efc2fbd9SStefano Zampini   PetscFunctionBegin;
2184efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2185efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
21864f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2187efc2fbd9SStefano Zampini   }
2188de9d7bd0SStefano Zampini   if (get) {
2189efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
21904f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
21914f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2192efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2193de9d7bd0SStefano Zampini   } else {
2194de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2195de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2196de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2197de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2198efc2fbd9SStefano Zampini   }
2199efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2200efc2fbd9SStefano Zampini }
2201efc2fbd9SStefano Zampini 
2202efc2fbd9SStefano Zampini #undef __FUNCT__
2203c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2204c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2205c263805aSStefano Zampini {
2206c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2207c263805aSStefano Zampini   PetscErrorCode ierr;
2208c263805aSStefano Zampini 
2209c263805aSStefano Zampini   PetscFunctionBegin;
2210c263805aSStefano Zampini   /* TODO: add error checking
2211c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2212c263805aSStefano Zampini     - cannot push before pop.
22131c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2214c263805aSStefano Zampini   */
22154f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2216efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2217efc2fbd9SStefano Zampini   }
2218c263805aSStefano Zampini   if (pop) {
2219a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22204f1b2e48SStefano Zampini       IS       is_p0;
22214f1b2e48SStefano Zampini       MatReuse reuse;
2222c263805aSStefano Zampini 
2223c263805aSStefano Zampini       /* extract B_0 */
22244f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
22254f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
22264f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
22274f1b2e48SStefano Zampini       }
22284f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
22294f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2230c263805aSStefano Zampini       /* remove rows and cols from local problem */
2231c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
223297d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
22334f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
22344f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2235a3df083aSStefano Zampini     } else {
2236a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2237a3df083aSStefano Zampini       PetscScalar *vals;
2238a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2239a3df083aSStefano Zampini 
2240a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2241a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2242a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
22430b5adadeSStefano Zampini         PetscInt *nnz;
2244a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2245a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2246a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2247331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2248331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2249331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2250331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2251331e053bSStefano Zampini         }
2252331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2253331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2254331e053bSStefano Zampini       }
2255a3df083aSStefano Zampini 
2256a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2257a3df083aSStefano Zampini         PetscScalar *array;
2258a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2259a3df083aSStefano Zampini 
2260a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2261a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2262a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2263a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2264a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2265a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2266a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2267a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2268a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2269a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2270a3df083aSStefano Zampini         cum = 0;
2271a3df083aSStefano Zampini         for (j=0;j<n;j++) {
227222db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2273a3df083aSStefano Zampini             vals[cum] = array[j];
2274a3df083aSStefano Zampini             idxs_ins[cum] = j;
2275a3df083aSStefano Zampini             cum++;
2276a3df083aSStefano Zampini           }
2277a3df083aSStefano Zampini         }
2278a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2279a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2280a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2281a3df083aSStefano Zampini       }
2282a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2283a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2284a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2285a3df083aSStefano Zampini     }
2286c263805aSStefano Zampini   } else { /* push */
2287a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22884f1b2e48SStefano Zampini       PetscInt i;
22894f1b2e48SStefano Zampini 
22904f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
22914f1b2e48SStefano Zampini         PetscScalar *B0_vals;
22924f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
22934f1b2e48SStefano Zampini 
22944f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22954f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
22967b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
22974f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
22984f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22994f1b2e48SStefano Zampini       }
2300c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2301c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2302a3df083aSStefano Zampini     } else {
2303a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2304a3df083aSStefano Zampini     }
2305c263805aSStefano Zampini   }
2306c263805aSStefano Zampini   PetscFunctionReturn(0);
2307c263805aSStefano Zampini }
2308c263805aSStefano Zampini 
2309c263805aSStefano Zampini #undef __FUNCT__
2310b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
231108122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2312b1b3d7a2SStefano Zampini {
2313b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
231408122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
231508122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
231608122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
231708122e43SStefano Zampini   PetscScalar     *work,lwork;
231808122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
231908122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
232008122e43SStefano Zampini   PetscReal       *eigs,thresh;
23211b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2322f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
232308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
232408122e43SStefano Zampini   PetscReal       *rwork;
232508122e43SStefano Zampini #endif
2326b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2327b1b3d7a2SStefano Zampini 
2328b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2329b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2330af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2331af25d912SStefano 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);
233206a4e24aSStefano Zampini 
2333fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2334fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2335fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2336fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
23371575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2338fd14bc51SStefano Zampini   }
2339fd14bc51SStefano Zampini 
2340e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2341e496cd5dSStefano 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);
2342e496cd5dSStefano Zampini   }
2343e496cd5dSStefano Zampini 
234408122e43SStefano Zampini   /* max size of subsets */
234508122e43SStefano Zampini   mss = 0;
234608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
234708122e43SStefano Zampini     PetscInt subset_size;
2348862806e4SStefano Zampini 
234908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
235008122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
235108122e43SStefano Zampini   }
235208122e43SStefano Zampini 
235308122e43SStefano Zampini   /* min/max and threshold */
235408122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2355f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
235608122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2357f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2358f6f667cfSStefano Zampini   if (nmin) {
2359f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2360f6f667cfSStefano Zampini   }
236108122e43SStefano Zampini 
236208122e43SStefano Zampini   /* allocate lapack workspace */
236308122e43SStefano Zampini   cum = cum2 = 0;
236408122e43SStefano Zampini   maxneigs = 0;
236508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
236608122e43SStefano Zampini     PetscInt n,subset_size;
2367f6f667cfSStefano Zampini 
236808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
236908122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
23709162d606SStefano Zampini     cum += subset_size;
23719162d606SStefano Zampini     cum2 += subset_size*n;
237208122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
237308122e43SStefano Zampini   }
237408122e43SStefano Zampini   if (mss) {
23759ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
237608122e43SStefano Zampini       PetscBLASInt B_itype = 1;
237708122e43SStefano Zampini       PetscBLASInt B_N = mss;
23784c6709b3SStefano Zampini       PetscReal    zero = 0.0;
23794c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
238008122e43SStefano Zampini 
238108122e43SStefano Zampini       B_lwork = -1;
238208122e43SStefano Zampini       S = NULL;
238308122e43SStefano Zampini       St = NULL;
2384a58a30b4SStefano Zampini       eigs = NULL;
2385a58a30b4SStefano Zampini       eigv = NULL;
2386a58a30b4SStefano Zampini       B_iwork = NULL;
2387a58a30b4SStefano Zampini       B_ifail = NULL;
2388d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2389d1710679SStefano Zampini       rwork = NULL;
2390d1710679SStefano Zampini #endif
23918bec7fa6SStefano Zampini       thresh = 1.0;
239208122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
239308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
239408122e43SStefano 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));
239508122e43SStefano Zampini #else
239608122e43SStefano 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));
239708122e43SStefano Zampini #endif
239808122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
239908122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
240008122e43SStefano Zampini     } else {
240108122e43SStefano Zampini         /* TODO */
240208122e43SStefano Zampini     }
240308122e43SStefano Zampini   } else {
240408122e43SStefano Zampini     lwork = 0;
240508122e43SStefano Zampini   }
240608122e43SStefano Zampini 
240708122e43SStefano Zampini   nv = 0;
2408d62866d3SStefano 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) */
2409d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
241008122e43SStefano Zampini   }
24114c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2412f6f667cfSStefano Zampini   if (allocated_S_St) {
2413f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2414f6f667cfSStefano Zampini   }
2415f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
241608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
241708122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
241808122e43SStefano Zampini #endif
24199162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
24209162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
24219162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
242208122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
24239162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
242408122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
242508122e43SStefano Zampini 
242608122e43SStefano Zampini   maxneigs = 0;
242772b8c272SStefano Zampini   cum = cumarray = 0;
24289162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
24299162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2430d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
243108122e43SStefano Zampini     const PetscInt *idxs;
243208122e43SStefano Zampini 
2433d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
243408122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
243508122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
243608122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
243708122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
24389162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
24399162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
244008122e43SStefano Zampini     }
2441d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
244208122e43SStefano Zampini   }
244308122e43SStefano Zampini 
244408122e43SStefano Zampini   if (mss) { /* multilevel */
244508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
244608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
244708122e43SStefano Zampini   }
244808122e43SStefano Zampini 
2449ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
245008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
245108122e43SStefano Zampini     const PetscInt *idxs;
24529d54b7f4SStefano Zampini     PetscReal      upper,lower;
2453862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
245408122e43SStefano Zampini     PetscBLASInt   B_N;
2455aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
245608122e43SStefano Zampini 
24579d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
24589d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
24599d54b7f4SStefano Zampini       lower = thresh;
24609d54b7f4SStefano Zampini     } else {
24619d54b7f4SStefano Zampini       upper = 1./thresh;
24629d54b7f4SStefano Zampini       lower = 0.;
24639d54b7f4SStefano Zampini     }
2464862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2465ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2466f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2467f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
24689ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2469aff50787SStefano Zampini         PetscInt j,k;
2470aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2471aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2472aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
247308122e43SStefano Zampini         }
247408122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2475aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2476aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2477aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2478aff50787SStefano Zampini           }
247908122e43SStefano Zampini         }
248008122e43SStefano Zampini       } else {
248108122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248208122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248308122e43SStefano Zampini       }
24848bec7fa6SStefano Zampini     } else {
2485f6f667cfSStefano Zampini       S = Sarray + cumarray;
2486f6f667cfSStefano Zampini       St = Starray + cumarray;
24878bec7fa6SStefano Zampini     }
2488aff50787SStefano Zampini     /* see if we can save some work */
2489b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2490aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2491aff50787SStefano Zampini     }
2492aff50787SStefano Zampini 
2493b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2494aff50787SStefano Zampini       B_neigs = 0;
2495aff50787SStefano Zampini     } else {
24969ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
249708122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2498f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
24994c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
25009552c7c7SStefano Zampini         PetscInt     nmin_s;
2501b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
250208122e43SStefano Zampini 
2503fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
25048bec7fa6SStefano 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]]);
2505fd14bc51SStefano Zampini         }
2506d16cbb6bSStefano Zampini 
2507b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2508b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2509b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2510b7ab4a40SStefano Zampini         }
2511b7ab4a40SStefano Zampini 
251208122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2513b7ab4a40SStefano Zampini         if (compute_range) {
2514d16cbb6bSStefano Zampini 
2515d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
251608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25179d54b7f4SStefano 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));
251808122e43SStefano Zampini #else
25199d54b7f4SStefano 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));
252008122e43SStefano Zampini #endif
2521b7ab4a40SStefano Zampini         } else if (!same_data) {
2522d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2523d16cbb6bSStefano Zampini           B_IL = 1;
2524d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
25259d54b7f4SStefano 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));
2526d16cbb6bSStefano Zampini #else
25279d54b7f4SStefano 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));
2528d16cbb6bSStefano Zampini #endif
2529b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2530b7ab4a40SStefano Zampini           PetscInt k;
2531b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2532b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2533b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2534b7ab4a40SStefano Zampini           nmin = nmax;
2535b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2536b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2537b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2538b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2539b7ab4a40SStefano Zampini           }
2540d16cbb6bSStefano Zampini         }
254108122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
254208122e43SStefano Zampini         if (B_ierr) {
25436c4ed002SBarry 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);
25446c4ed002SBarry 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);
25456c4ed002SBarry 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);
254608122e43SStefano Zampini         }
254708122e43SStefano Zampini 
254808122e43SStefano Zampini         if (B_neigs > nmax) {
2549fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2550fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2551fd14bc51SStefano Zampini           }
25529d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
255308122e43SStefano Zampini           B_neigs = nmax;
255408122e43SStefano Zampini         }
255508122e43SStefano Zampini 
25569552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
25579552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
255808122e43SStefano Zampini           PetscBLASInt B_neigs2;
255908122e43SStefano Zampini 
25609d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2561f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
25629d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
25639d54b7f4SStefano Zampini           } else {
25649d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
25659d54b7f4SStefano Zampini             B_IU = nmin_s;
25669d54b7f4SStefano Zampini           }
2567fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2568fd14bc51SStefano 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);
2569fd14bc51SStefano Zampini           }
25709ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
25711ae86dd6SStefano Zampini             PetscInt j,k;
257208122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
25731ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
25741ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
25751ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
257608122e43SStefano Zampini               }
257708122e43SStefano Zampini             }
257808122e43SStefano Zampini           } else {
257908122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258008122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258108122e43SStefano Zampini           }
258208122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
258308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25849d54b7f4SStefano 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));
258508122e43SStefano Zampini #else
25869d54b7f4SStefano 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));
258708122e43SStefano Zampini #endif
258808122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
258908122e43SStefano Zampini           B_neigs += B_neigs2;
259008122e43SStefano Zampini         }
259108122e43SStefano Zampini         if (B_ierr) {
25926c4ed002SBarry 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);
25936c4ed002SBarry 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);
25946c4ed002SBarry 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);
259508122e43SStefano Zampini         }
2596fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2597ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
259808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
259908122e43SStefano Zampini             if (eigs[j] == 0.0) {
2600ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
260108122e43SStefano Zampini             } else {
26029d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2603ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
26049d54b7f4SStefano Zampini               } else {
26059d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
26069d54b7f4SStefano Zampini               }
2607fd14bc51SStefano Zampini             }
260808122e43SStefano Zampini           }
260908122e43SStefano Zampini         }
261008122e43SStefano Zampini       } else {
261108122e43SStefano Zampini           /* TODO */
261208122e43SStefano Zampini       }
2613aff50787SStefano Zampini     }
26146c3e6151SStefano Zampini     /* change the basis back to the original one */
26156c3e6151SStefano Zampini     if (sub_schurs->change) {
261672b8c272SStefano Zampini       Mat change,phi,phit;
26176c3e6151SStefano Zampini 
26186c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26196c3e6151SStefano Zampini         PetscInt ii;
26206c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
26216c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26226c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2623684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2624684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2625684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2626684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2627684229deSStefano Zampini #else
26286c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2629684229deSStefano Zampini #endif
26306c3e6151SStefano Zampini           }
26316c3e6151SStefano Zampini         }
26326c3e6151SStefano Zampini       }
263372b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
26346c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
263572b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
26366c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
26376c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
26386c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
26396c3e6151SStefano Zampini     }
26408bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
26418bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
26429162d606SStefano Zampini     if (B_neigs) {
26439162d606SStefano 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);
2644fd14bc51SStefano Zampini 
2645fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26469552c7c7SStefano Zampini         PetscInt ii;
26479552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2648ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26499552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2650ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2651ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2652ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2653ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2654ac47001eSStefano Zampini #else
2655ac47001eSStefano 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);
2656ac47001eSStefano Zampini #endif
26579552c7c7SStefano Zampini           }
26589552c7c7SStefano Zampini         }
2659fd14bc51SStefano Zampini       }
26609162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
26619162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
26629162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
26639162d606SStefano Zampini       cum++;
266408122e43SStefano Zampini     }
266508122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
266608122e43SStefano Zampini     /* shift for next computation */
266708122e43SStefano Zampini     cumarray += subset_size*subset_size;
266808122e43SStefano Zampini   }
2669fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2670fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2671fd14bc51SStefano Zampini   }
267208122e43SStefano Zampini 
267308122e43SStefano Zampini   if (mss) {
267408122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
267508122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2676f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2677f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2678f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
267908122e43SStefano Zampini   }
2680f6f667cfSStefano Zampini   if (allocated_S_St) {
2681f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2682f6f667cfSStefano Zampini   }
2683f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
268408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
268508122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
268608122e43SStefano Zampini #endif
268708122e43SStefano Zampini   if (pcbddc->dbg_flag) {
26881b968477SStefano Zampini     PetscInt maxneigs_r;
2689b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
26909b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
269108122e43SStefano Zampini   }
269208122e43SStefano Zampini   PetscFunctionReturn(0);
269308122e43SStefano Zampini }
2694b1b3d7a2SStefano Zampini 
2695674ae819SStefano Zampini #undef __FUNCT__
2696c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2697c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2698c8587f34SStefano Zampini {
26998629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2700c8587f34SStefano Zampini   PetscErrorCode ierr;
2701c8587f34SStefano Zampini 
2702c8587f34SStefano Zampini   PetscFunctionBegin;
2703f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
27045e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2705c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2706c8587f34SStefano Zampini 
2707684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
27080fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2709684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2710c8587f34SStefano Zampini 
27118629588bSStefano Zampini   /*
27128629588bSStefano Zampini      Setup local correction and local part of coarse basis.
27138629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
27148629588bSStefano Zampini   */
271547f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
27168629588bSStefano Zampini 
27178629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
27188629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
27198629588bSStefano Zampini 
27208629588bSStefano Zampini   /* free */
27218629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2722c8587f34SStefano Zampini   PetscFunctionReturn(0);
2723c8587f34SStefano Zampini }
2724c8587f34SStefano Zampini 
2725c8587f34SStefano Zampini #undef __FUNCT__
2726674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2727674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2728674ae819SStefano Zampini {
2729674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2730674ae819SStefano Zampini   PetscErrorCode ierr;
2731674ae819SStefano Zampini 
2732674ae819SStefano Zampini   PetscFunctionBegin;
2733674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
273430368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2735674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2736785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2737674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2738f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2739f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2740785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
274163602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
274263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2743674ae819SStefano Zampini   PetscFunctionReturn(0);
2744674ae819SStefano Zampini }
2745674ae819SStefano Zampini 
2746674ae819SStefano Zampini #undef __FUNCT__
2747674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2748674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2749674ae819SStefano Zampini {
2750674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
27514f1b2e48SStefano Zampini   PetscInt       i;
2752674ae819SStefano Zampini   PetscErrorCode ierr;
2753674ae819SStefano Zampini 
2754674ae819SStefano Zampini   PetscFunctionBegin;
2755a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2756b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2757674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
275816909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
27591dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2760674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2761669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2762fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2763a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2764674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
27654f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
27664f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
27674f1b2e48SStefano Zampini   }
27684f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2769b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2770b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2771b334f244SStefano Zampini   }
2772*c703fcc7SStefano Zampini   pcbddc->graphanalyzed = PETSC_FALSE;
2773674ae819SStefano Zampini   PetscFunctionReturn(0);
2774674ae819SStefano Zampini }
2775674ae819SStefano Zampini 
2776674ae819SStefano Zampini #undef __FUNCT__
2777674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2778674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2779674ae819SStefano Zampini {
2780674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2781674ae819SStefano Zampini   PetscErrorCode ierr;
2782674ae819SStefano Zampini 
2783674ae819SStefano Zampini   PetscFunctionBegin;
2784674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
278558da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2786ca92afb2SStefano Zampini     PetscScalar *array;
278706656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
278806656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
278958da7f69SStefano Zampini   }
2790674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2791674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
279215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
279315aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2794674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2795674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2796674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
279706656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2798674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2799674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28008ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2801674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2802674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2803674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2804f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2805f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2806f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2807f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2808727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
28090e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2810f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
281170cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
281281d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
28130369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
28141dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
28154f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
28168b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2817ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2818ca92afb2SStefano Zampini     PetscInt i;
2819ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2820ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2821ca92afb2SStefano Zampini     }
2822ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2823ca92afb2SStefano Zampini   }
28244f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2825674ae819SStefano Zampini   PetscFunctionReturn(0);
2826674ae819SStefano Zampini }
2827674ae819SStefano Zampini 
2828674ae819SStefano Zampini #undef __FUNCT__
2829f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2830f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
28316bfb1811SStefano Zampini {
28326bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
28336bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
28346bfb1811SStefano Zampini   VecType        impVecType;
28354f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
28366bfb1811SStefano Zampini   PetscErrorCode ierr;
28376bfb1811SStefano Zampini 
28386bfb1811SStefano Zampini   PetscFunctionBegin;
28396c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2840e7b262bdSStefano Zampini   /* get sizes */
28414f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2842b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
28436bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2844e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2845e7b262bdSStefano Zampini   /* R nodes */
2846e7b262bdSStefano Zampini   old_size = -1;
2847e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2848e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2849e7b262bdSStefano Zampini   }
2850e7b262bdSStefano Zampini   if (n_R != old_size) {
2851e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2852e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28536bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
28546bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
28556bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
28566bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2857e7b262bdSStefano Zampini   }
2858e7b262bdSStefano Zampini   /* local primal dofs */
2859e7b262bdSStefano Zampini   old_size = -1;
2860e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2861e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2862e7b262bdSStefano Zampini   }
2863e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2864e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
286583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2866e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
28676bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2868e7b262bdSStefano Zampini   }
2869e7b262bdSStefano Zampini   /* local explicit constraints */
2870e7b262bdSStefano Zampini   old_size = -1;
2871e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2872e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2873e7b262bdSStefano Zampini   }
2874e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2875e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
287683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
287783b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
287883b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
287983b7ccabSStefano Zampini   }
28806bfb1811SStefano Zampini   PetscFunctionReturn(0);
28816bfb1811SStefano Zampini }
28826bfb1811SStefano Zampini 
28836bfb1811SStefano Zampini #undef __FUNCT__
288447f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
288547f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
288688ebb749SStefano Zampini {
288725084f0cSStefano Zampini   PetscErrorCode  ierr;
288825084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
288988ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
289088ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2891d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
289225084f0cSStefano Zampini   /* submatrices of local problem */
289380677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
289406656605SStefano Zampini   /* submatrices of local coarse problem */
289506656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
289625084f0cSStefano Zampini   /* working matrices */
289706656605SStefano Zampini   Mat             C_CR;
289825084f0cSStefano Zampini   /* additional working stuff */
289906656605SStefano Zampini   PC              pc_R;
29004f1b2e48SStefano Zampini   Mat             F;
29015cbda25cSStefano Zampini   Vec             dummy_vec;
2902a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
290325084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
290406656605SStefano Zampini   PetscScalar     *work;
290506656605SStefano Zampini   PetscInt        *idx_V_B;
2906ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
290706656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2908ffd830a3SStefano Zampini 
290925084f0cSStefano Zampini   /* some shortcuts to scalars */
291006656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
291188ebb749SStefano Zampini 
291288ebb749SStefano Zampini   PetscFunctionBegin;
29139a962809SStefano 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");
2914ffd830a3SStefano Zampini 
2915ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2916b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29174f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2918b371cd4fSStefano Zampini   n_B = pcis->n_B;
2919b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
292088ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
292188ebb749SStefano Zampini 
292288ebb749SStefano Zampini   /* vertices in boundary numbering */
2923785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
29240e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
29256c4ed002SBarry 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);
292688ebb749SStefano Zampini 
292706656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2928019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
292906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
293006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
293106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
293206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
293306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
293406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
293506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
293606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
293706656605SStefano Zampini 
293806656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
293906656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
294006656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
294106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
294206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2943ffd830a3SStefano Zampini   lda_rhs = n_R;
2944a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
294506656605SStefano Zampini   if (isLU || isILU || isCHOL) {
294606656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2947b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2948df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2949d62866d3SStefano Zampini     MatFactorType      type;
2950d62866d3SStefano Zampini 
2951df4d28bfSStefano Zampini     F = reuse_solver->F;
29526816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2953d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2954ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
295522db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
295606656605SStefano Zampini   } else {
295706656605SStefano Zampini     F = NULL;
295806656605SStefano Zampini   }
295906656605SStefano Zampini 
2960ffd830a3SStefano Zampini   /* allocate workspace */
2961ffd830a3SStefano Zampini   n = 0;
2962ffd830a3SStefano Zampini   if (n_constraints) {
2963ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2964ffd830a3SStefano Zampini   }
2965ffd830a3SStefano Zampini   if (n_vertices) {
2966ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2967ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2968ffd830a3SStefano Zampini   }
2969ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2970ffd830a3SStefano Zampini 
29715cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
29725cbda25cSStefano Zampini   dummy_vec = NULL;
29735cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
29745cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
29755cbda25cSStefano Zampini   }
29765cbda25cSStefano Zampini 
297788ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
297888ebb749SStefano Zampini   if (n_constraints) {
297972b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
298006656605SStefano Zampini     IS          is_aux;
298180677318SStefano Zampini     PetscScalar *array,*array2;
298206656605SStefano Zampini 
2983f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
298480677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
298588ebb749SStefano Zampini 
298625084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
298725084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
29888ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
298972b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
299088ebb749SStefano Zampini 
299180677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
299280677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2993ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
299488ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
299506656605SStefano Zampini       const PetscScalar *row_cmat_values;
299606656605SStefano Zampini       const PetscInt    *row_cmat_indices;
299706656605SStefano Zampini       PetscInt          size_of_constraint,j;
299888ebb749SStefano Zampini 
299906656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300006656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
3001ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
300206656605SStefano Zampini       }
300306656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300406656605SStefano Zampini     }
3005ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
300606656605SStefano Zampini     if (F) {
300706656605SStefano Zampini       Mat B;
300806656605SStefano Zampini 
3009ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
3010a3df083aSStefano Zampini       if (need_benign_correction) {
3011df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3012a3df083aSStefano Zampini 
301372b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
301472b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3015a3df083aSStefano Zampini       }
301680677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
3017a3df083aSStefano Zampini       if (need_benign_correction) {
3018a3df083aSStefano Zampini         PetscScalar        *marr;
3019df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3020a3df083aSStefano Zampini 
3021a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
30225cbda25cSStefano Zampini         if (lda_rhs != n_R) {
30235cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
30245cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30255cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
30265cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30275cbda25cSStefano Zampini           }
30285cbda25cSStefano Zampini         } else {
3029a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3030a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30315cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3032a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3033a3df083aSStefano Zampini           }
30345cbda25cSStefano Zampini         }
3035a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3036a3df083aSStefano Zampini       }
303706656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
303806656605SStefano Zampini     } else {
303980677318SStefano Zampini       PetscScalar *marr;
304080677318SStefano Zampini 
304180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
304206656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3043ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3044ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
304506656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
304606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
304706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
304806656605SStefano Zampini       }
304980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
305006656605SStefano Zampini     }
305180677318SStefano Zampini     if (!pcbddc->switch_static) {
305280677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
305380677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
305480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
305580677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3056ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
305780677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
305880677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
305980677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
306080677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
306180677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
306280677318SStefano Zampini       }
306380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
306480677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
306572b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
306680677318SStefano Zampini     } else {
3067ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3068ffd830a3SStefano Zampini         IS dummy;
3069ffd830a3SStefano Zampini 
3070ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
307172b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3072ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3073ffd830a3SStefano Zampini       } else {
307480677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
307580677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3076ffd830a3SStefano Zampini       }
307725084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
307880677318SStefano Zampini     }
307980677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
308080677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
308180677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
308206656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
308306656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
308480677318SStefano Zampini     if (isCHOL) {
308580677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
308680677318SStefano Zampini     } else {
308725084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
308880677318SStefano Zampini     }
308980677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
309006656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
309125084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
309225084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
309325084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
309480677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
309572b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
309672b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
309706656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
309806656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3099f4ddd8eeSStefano Zampini   }
3100fc227af8SStefano Zampini 
3101fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
310288ebb749SStefano Zampini   if (n_vertices) {
310306656605SStefano Zampini     IS is_aux;
31043a50541eSStefano Zampini 
3105b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
31066816873aSStefano Zampini       IS tis;
31076816873aSStefano Zampini 
31086816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
31096816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
31106816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
31116816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
31126816873aSStefano Zampini     } else {
31133a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
31146816873aSStefano Zampini     }
31159577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
31169577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
311704708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
311825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
311988ebb749SStefano Zampini   }
312088ebb749SStefano Zampini 
312188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3122f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
312306656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
312406656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
312506656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
312606656605SStefano Zampini     }
3127f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
312806656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
312906656605SStefano Zampini       PetscScalar *marray;
313006656605SStefano Zampini 
313106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
313206656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3133f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3134f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3135f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3136f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3137f4ddd8eeSStefano Zampini     }
3138f4ddd8eeSStefano Zampini   }
313906656605SStefano Zampini 
3140f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
314106656605SStefano Zampini     PetscScalar *marray;
314288ebb749SStefano Zampini 
314306656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31448eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
314506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
314688ebb749SStefano Zampini     }
31473301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
314806656605SStefano Zampini       n *= 2;
314988ebb749SStefano Zampini     }
315006656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
315106656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
315206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31538eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
315406656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
315506656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
315688ebb749SStefano Zampini     }
31573301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
315806656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
31598eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
316006656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
316106656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
316288ebb749SStefano Zampini       }
316388ebb749SStefano Zampini     } else {
3164c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3165c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
31661b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3167c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3168c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3169c0553b1fSStefano Zampini       }
317088ebb749SStefano Zampini     }
317106656605SStefano Zampini   }
3172019a44ceSStefano Zampini 
317306656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
31744f1b2e48SStefano Zampini   p0_lidx_I = NULL;
31754f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3176d12edf2fSStefano Zampini     const PetscInt *idxs;
3177d12edf2fSStefano Zampini 
3178d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
31794f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
31804f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
31814f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
31824f1b2e48SStefano Zampini     }
3183d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3184d12edf2fSStefano Zampini   }
3185d16cbb6bSStefano Zampini 
318606656605SStefano Zampini   /* vertices */
318706656605SStefano Zampini   if (n_vertices) {
318816f15bc4SStefano Zampini 
3189af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
319004708bb6SStefano Zampini 
319116f15bc4SStefano Zampini     if (n_R) {
319214393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
319306656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
319416f15bc4SStefano Zampini       PetscScalar  *x,*y;
319504708bb6SStefano Zampini       PetscBool    isseqaij;
319606656605SStefano Zampini 
319721eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
319814393ed6SStefano Zampini       if (need_benign_correction) {
319914393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
320014393ed6SStefano Zampini         IS                     is_p0;
320114393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
320214393ed6SStefano Zampini 
320314393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
320414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
320514393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3206af25d912SStefano 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);
320714393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
320814393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
320914393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
321014393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
321114393ed6SStefano Zampini       }
321214393ed6SStefano Zampini 
3213ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3214af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3215ffd830a3SStefano Zampini       } else {
3216ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3217ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3218ca92afb2SStefano Zampini         PetscInt       n;
3219ca92afb2SStefano Zampini         PetscBool      flg_row;
3220ffd830a3SStefano Zampini 
3221ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3222ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
32239d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3224ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3225ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3226ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3227ca92afb2SStefano Zampini           PetscInt j;
3228ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3229ffd830a3SStefano Zampini         }
3230ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3231ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3232ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3233ffd830a3SStefano Zampini       }
3234ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3235a3df083aSStefano Zampini       if (need_benign_correction) {
3236df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3237a3df083aSStefano Zampini         PetscScalar        *marr;
3238a3df083aSStefano Zampini 
3239a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
324014393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
324114393ed6SStefano Zampini 
324214393ed6SStefano Zampini                | 0 0  0 | (V)
324314393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
324414393ed6SStefano Zampini                | 0 0 -1 | (p0)
324514393ed6SStefano Zampini 
324614393ed6SStefano Zampini         */
3247df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
324814393ed6SStefano Zampini           const PetscScalar *vals;
324914393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
325014393ed6SStefano Zampini           PetscInt          n,j,nz;
325114393ed6SStefano Zampini 
3252df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3253df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
325414393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
325514393ed6SStefano Zampini           for (j=0;j<n;j++) {
325614393ed6SStefano Zampini             PetscScalar val = vals[j];
325714393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
325814393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
325914393ed6SStefano Zampini           }
326014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3261df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
326214393ed6SStefano Zampini         }
326372b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
326472b8c272SStefano Zampini       }
326572b8c272SStefano Zampini       if (F) {
326614393ed6SStefano Zampini         /* need to correct the rhs */
326772b8c272SStefano Zampini         if (need_benign_correction) {
326872b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
326972b8c272SStefano Zampini           PetscScalar        *marr;
327072b8c272SStefano Zampini 
327172b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
32725cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32735cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32745cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32755cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
32765cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32775cbda25cSStefano Zampini             }
32785cbda25cSStefano Zampini           } else {
3279a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3280a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
32815cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3282a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3283a3df083aSStefano Zampini             }
32845cbda25cSStefano Zampini           }
3285a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3286a3df083aSStefano Zampini         }
328706656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
328814393ed6SStefano Zampini         /* need to correct the solution */
3289a3df083aSStefano Zampini         if (need_benign_correction) {
3290df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3291a3df083aSStefano Zampini           PetscScalar        *marr;
3292a3df083aSStefano Zampini 
3293a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
32945cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32955cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32965cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32975cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
32985cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32995cbda25cSStefano Zampini             }
33005cbda25cSStefano Zampini           } else {
3301a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3302a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
33035cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3304a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3305a3df083aSStefano Zampini             }
33065cbda25cSStefano Zampini           }
3307a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3308a3df083aSStefano Zampini         }
330906656605SStefano Zampini       } else {
331006656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
331106656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3312ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3313ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
331406656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
331506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
331606656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
331706656605SStefano Zampini         }
331806656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
331906656605SStefano Zampini       }
332080677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3321ffd830a3SStefano Zampini       /* S_VV and S_CV */
332206656605SStefano Zampini       if (n_constraints) {
332306656605SStefano Zampini         Mat B;
332480677318SStefano Zampini 
3325ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
332680677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3327ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3328ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
332980677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333080677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333180677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
333280677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
333380677318SStefano Zampini         }
3334ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
333580677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
333680677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3337ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
333880677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
333906656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3340ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3341ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
334206656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
334306656605SStefano Zampini       }
334404708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
334504708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3346511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
334704708bb6SStefano Zampini       }
3348ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3349ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3350ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3351ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3352ffd830a3SStefano Zampini       }
335306656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
335414393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
335514393ed6SStefano Zampini       if (need_benign_correction) {
3356df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
335714393ed6SStefano Zampini         PetscScalar      *marr,*sums;
335814393ed6SStefano Zampini 
335914393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
336014393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3361df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
336214393ed6SStefano Zampini           const PetscScalar *vals;
336314393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
336414393ed6SStefano Zampini           PetscInt          n,j,nz;
336514393ed6SStefano Zampini 
3366df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3367df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
336814393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
336914393ed6SStefano Zampini             PetscInt k;
337014393ed6SStefano Zampini             sums[j] = 0.;
337114393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
337214393ed6SStefano Zampini           }
337314393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
337414393ed6SStefano Zampini           for (j=0;j<n;j++) {
337514393ed6SStefano Zampini             PetscScalar val = vals[j];
337614393ed6SStefano Zampini             PetscInt k;
337714393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
337814393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
337914393ed6SStefano Zampini             }
338014393ed6SStefano Zampini           }
338114393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3382df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
338314393ed6SStefano Zampini         }
338414393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
338514393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
338614393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
338714393ed6SStefano Zampini       }
338880677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
338906656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
339006656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
339106656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
339206656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
339306656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
339406656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
339506656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3396d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3397019a44ceSStefano Zampini     } else {
3398d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3399d16cbb6bSStefano Zampini     }
340021eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3401d16cbb6bSStefano Zampini 
340206656605SStefano Zampini     /* coarse basis functions */
340306656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
340416f15bc4SStefano Zampini       PetscScalar *y;
340516f15bc4SStefano Zampini 
3406ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
340706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
340806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
340906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341106656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
341206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
341306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
341406656605SStefano Zampini 
341506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34164f1b2e48SStefano Zampini         PetscInt j;
34174f1b2e48SStefano Zampini 
341806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
341906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
342006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34234f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
342406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
342506656605SStefano Zampini       }
342606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
342706656605SStefano Zampini     }
342804708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
342904708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
343006656605SStefano Zampini   }
34315cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
343206656605SStefano Zampini 
343306656605SStefano Zampini   if (n_constraints) {
343406656605SStefano Zampini     Mat B;
343506656605SStefano Zampini 
3436ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
343706656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
343880677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
343906656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
344006656605SStefano Zampini     if (n_vertices) {
344180677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
344280677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
344380677318SStefano Zampini       } else {
344480677318SStefano Zampini         Mat S_VCt;
344580677318SStefano Zampini 
3446ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3447ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
344872b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3449ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3450ffd830a3SStefano Zampini         }
345180677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
345280677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
345380677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
345480677318SStefano Zampini       }
345506656605SStefano Zampini     }
345606656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
345706656605SStefano Zampini     /* coarse basis functions */
345806656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
345906656605SStefano Zampini       PetscScalar *y;
346006656605SStefano Zampini 
3461ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
346206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
346306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
346406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
346706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
346806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34694f1b2e48SStefano Zampini         PetscInt j;
34704f1b2e48SStefano Zampini 
347106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
347206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
347306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34764f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
347706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
347806656605SStefano Zampini       }
347906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
348006656605SStefano Zampini     }
348106656605SStefano Zampini   }
348280677318SStefano Zampini   if (n_constraints) {
348380677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
348480677318SStefano Zampini   }
34854f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
348672b8c272SStefano Zampini 
348772b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
348872b8c272SStefano Zampini   if (pcbddc->benign_n) {
348972b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
349072b8c272SStefano Zampini     IS          is_dummy;
349172b8c272SStefano Zampini     PetscScalar *data;
349272b8c272SStefano Zampini     PetscInt    j;
349372b8c272SStefano Zampini 
349472b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
349572b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
349672b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
349772b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
349886c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
349972b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
350072b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
350172b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
350272b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
350372b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
350472b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
350572b8c272SStefano Zampini       }
350672b8c272SStefano Zampini     }
350772b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
350872b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
350972b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
351072b8c272SStefano Zampini   }
3511019a44ceSStefano Zampini 
351206656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
35133301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3514ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3515ffd830a3SStefano Zampini     PetscScalar *marray;
351606656605SStefano Zampini 
351706656605SStefano Zampini     if (n_constraints) {
3518ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
351906656605SStefano Zampini 
3520af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
352106656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3522ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
352316f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
352406656605SStefano Zampini       if (n_vertices) {
3525ffd830a3SStefano Zampini         Mat S_VCT;
352606656605SStefano Zampini 
352706656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3528ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
352916f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
353006656605SStefano Zampini       }
3531ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
35325b782168SStefano Zampini     } else {
35335b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
353406656605SStefano Zampini     }
353516f15bc4SStefano Zampini     if (n_vertices && n_R) {
3536ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3537ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3538ffd830a3SStefano Zampini       PetscInt       n;
3539ffd830a3SStefano Zampini       PetscBool      flg_row;
354006656605SStefano Zampini 
3541ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3542af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3543ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3544ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3545ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3546ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3547ffd830a3SStefano Zampini         PetscInt j;
3548ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3549ffd830a3SStefano Zampini       }
3550ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3551ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3552ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
355306656605SStefano Zampini     }
355406656605SStefano Zampini 
3555ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3556ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3557ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3558ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3559ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
356006656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
356106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
356206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
356306656605SStefano Zampini     }
3564ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
35655b782168SStefano Zampini     if (B_C) {
3566ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3567ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3568ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3569ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3570ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3571ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3572ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
357306656605SStefano Zampini       }
3574ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
35755b782168SStefano Zampini     }
357606656605SStefano Zampini     /* coarse basis functions */
357706656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
357806656605SStefano Zampini       PetscScalar *y;
357906656605SStefano Zampini 
3580ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
358106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
358206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
358306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
358406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
358506656605SStefano Zampini       if (i<n_vertices) {
358606656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
358706656605SStefano Zampini       }
358806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
358906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
359006656605SStefano Zampini 
359106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
359206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
359306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
359406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
359506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
359606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
359706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
359806656605SStefano Zampini       }
359906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
360006656605SStefano Zampini     }
3601ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3602ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
360306656605SStefano Zampini   }
3604d62866d3SStefano Zampini   /* free memory */
360588ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
360606656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
360706656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
360806656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
360906656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3610d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3611d62866d3SStefano Zampini   if (n_vertices) {
3612d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3613d62866d3SStefano Zampini   }
3614d62866d3SStefano Zampini   if (n_constraints) {
3615d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3616d62866d3SStefano Zampini   }
361788ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
361888ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
361988ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3620d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
362188ebb749SStefano Zampini     Mat         coarse_sub_mat;
362225084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
362388ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
362488ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
362588ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
36268bec7fa6SStefano Zampini     Mat         C_B,CPHI;
36278bec7fa6SStefano Zampini     IS          is_dummy;
36288bec7fa6SStefano Zampini     Vec         mones;
362988ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
363088ebb749SStefano Zampini     PetscReal   real_value;
363188ebb749SStefano Zampini 
3632a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3633a3df083aSStefano Zampini       Mat A;
3634a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3635a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3636a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3637a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3638a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3639a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3640a3df083aSStefano Zampini     } else {
364188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
364288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
364388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
364488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3645a3df083aSStefano Zampini     }
364688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
364788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3648ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
364988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
365088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
365188ebb749SStefano Zampini     }
365288ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
365388ebb749SStefano Zampini 
365425084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36553301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
365625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3657ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
365888ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
365988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
366088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366188ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
366388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
366688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
366988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367088ebb749SStefano Zampini     } else {
367188ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
367288ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
367388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
367588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
367888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367988ebb749SStefano Zampini     }
368088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3683511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
36844f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3685fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3686d12edf2fSStefano Zampini       PetscScalar *data,*data2;
36874f1b2e48SStefano Zampini       PetscInt    j;
3688d12edf2fSStefano Zampini 
36894f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3690fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3691d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
369286c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3693d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3694d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
36954f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
36964f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3697d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
36984f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
36994f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
37004f1b2e48SStefano Zampini         }
3701d12edf2fSStefano Zampini       }
3702d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3703d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3704d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3705d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3706d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3707d12edf2fSStefano Zampini     }
3708d12edf2fSStefano Zampini #if 0
3709d12edf2fSStefano Zampini   {
3710d12edf2fSStefano Zampini     PetscViewer viewer;
3711d12edf2fSStefano Zampini     char filename[256];
3712ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3713d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3714d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3715ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3716ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3717ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3718d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
371972b8c272SStefano Zampini     if (save_change) {
372072b8c272SStefano Zampini       Mat phi_B;
372172b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
372272b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
372372b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
372472b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
372572b8c272SStefano Zampini     } else {
3726ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3727ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
372872b8c272SStefano Zampini     }
3729ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3730ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3731ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3732ffd830a3SStefano Zampini     }
3733ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3734ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3735ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3736ffd830a3SStefano Zampini     }
373772b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3738ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3739ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3740ffd830a3SStefano Zampini     }
3741d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3742d12edf2fSStefano Zampini   }
3743d12edf2fSStefano Zampini #endif
374481d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
37458bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
37461575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
374706656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
37488bec7fa6SStefano Zampini 
37498bec7fa6SStefano Zampini     /* check constraints */
3750a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3751a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
37524f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
37538bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3754a00504b5SStefano Zampini     } else {
3755a00504b5SStefano Zampini       PetscScalar *data;
3756a00504b5SStefano Zampini       Mat         tmat;
3757a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3758a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3759a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3760a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3761a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3762a00504b5SStefano Zampini     }
37638bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
37648bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
37658bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
37668bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3767bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3768ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3769bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3770bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3771bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3772bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3773bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
377488ebb749SStefano Zampini     }
37758bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
37768bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
37778bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37788bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
377925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
378088ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
378188ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
378288ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
378388ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
378488ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
378588ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
378688ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
378788ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
378888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
378988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3790ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
379188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
379288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
379388ebb749SStefano Zampini     }
379488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
379588ebb749SStefano Zampini   }
37968629588bSStefano Zampini   /* get back data */
37978629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
379888ebb749SStefano Zampini   PetscFunctionReturn(0);
379988ebb749SStefano Zampini }
380088ebb749SStefano Zampini 
380188ebb749SStefano Zampini #undef __FUNCT__
3802d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3803d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3804aa0d41d4SStefano Zampini {
3805d65f70fdSStefano Zampini   Mat            *work_mat;
3806d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3807d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3808c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3809aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3810aa0d41d4SStefano Zampini 
3811aa0d41d4SStefano Zampini   PetscFunctionBegin;
3812d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3813d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3814d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3815d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3816aa0d41d4SStefano Zampini 
3817d65f70fdSStefano Zampini   if (!rsorted) {
3818906d46d4SStefano Zampini     const PetscInt *idxs;
3819906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3820aa0d41d4SStefano Zampini 
3821d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3822d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3823d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3824d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3825aa0d41d4SStefano Zampini     }
3826d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3827d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3828d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3829d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3830aa0d41d4SStefano Zampini     }
3831d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3832d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3833d65f70fdSStefano Zampini   } else {
3834d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3835d65f70fdSStefano Zampini     isrow_s = isrow;
3836aa0d41d4SStefano Zampini   }
3837906d46d4SStefano Zampini 
3838d65f70fdSStefano Zampini   if (!csorted) {
3839d65f70fdSStefano Zampini     if (isrow == iscol) {
3840d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3841d65f70fdSStefano Zampini       iscol_s = isrow_s;
3842d65f70fdSStefano Zampini     } else {
3843d65f70fdSStefano Zampini       const PetscInt *idxs;
3844d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3845906d46d4SStefano Zampini 
3846d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3847d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3848d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3849d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3850d65f70fdSStefano Zampini       }
3851d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3852d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3853d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3854d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3855d65f70fdSStefano Zampini       }
3856d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3857d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3858d65f70fdSStefano Zampini     }
3859d65f70fdSStefano Zampini   } else {
3860d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3861d65f70fdSStefano Zampini     iscol_s = iscol;
3862d65f70fdSStefano Zampini   }
3863d65f70fdSStefano Zampini 
3864d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3865d65f70fdSStefano Zampini 
3866d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3867906d46d4SStefano Zampini     Mat      new_mat;
3868d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3869906d46d4SStefano Zampini 
3870d65f70fdSStefano Zampini     if (!rsorted) {
3871d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3872d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3873d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3874d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3875906d46d4SStefano Zampini       }
3876d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3877d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3878d65f70fdSStefano Zampini     } else {
3879d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3880906d46d4SStefano Zampini     }
3881d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3882d65f70fdSStefano Zampini 
3883d65f70fdSStefano Zampini     if (!csorted) {
3884d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3885d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3886d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3887d65f70fdSStefano Zampini       } else {
3888d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3889d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3890d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3891d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3892d65f70fdSStefano Zampini         }
3893d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3894d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3895d65f70fdSStefano Zampini       }
3896d65f70fdSStefano Zampini     } else {
3897d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3898d65f70fdSStefano Zampini     }
3899d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3900d65f70fdSStefano Zampini 
3901d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3902d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3903d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3904d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3905d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3906d65f70fdSStefano Zampini   }
3907d65f70fdSStefano Zampini 
3908d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3909d65f70fdSStefano Zampini   *B = work_mat[0];
3910d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3911d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3912d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3913d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3914d65f70fdSStefano Zampini }
3915d65f70fdSStefano Zampini 
3916d65f70fdSStefano Zampini #undef __FUNCT__
39175e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
39185e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3919aa0d41d4SStefano Zampini {
3920aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
39215e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3922d65f70fdSStefano Zampini   Mat            new_mat;
39235e8657edSStefano Zampini   IS             is_local,is_global;
3924d65f70fdSStefano Zampini   PetscInt       local_size;
3925d65f70fdSStefano Zampini   PetscBool      isseqaij;
3926aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3927aa0d41d4SStefano Zampini 
3928aa0d41d4SStefano Zampini   PetscFunctionBegin;
3929aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
39305e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
39315e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3932b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3933aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3934d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3935aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3936906d46d4SStefano Zampini 
3937906d46d4SStefano Zampini   /* check */
3938906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3939906d46d4SStefano Zampini     Vec       x,x_change;
3940906d46d4SStefano Zampini     PetscReal error;
3941906d46d4SStefano Zampini 
39425e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3943906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
39445e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3945e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3946e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3947d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3948e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3949e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3950906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3951906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3952906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3953906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3954906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3955906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3956906d46d4SStefano Zampini   }
3957906d46d4SStefano Zampini 
395822d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
39599b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
396022d5777bSStefano Zampini   if (isseqaij) {
3961a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3962a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3963aa0d41d4SStefano Zampini   } else {
3964a00504b5SStefano Zampini     Mat work_mat;
39651cf9b237SStefano Zampini 
3966a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3967aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3968a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
39691d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3970aa0d41d4SStefano Zampini   }
39713301b35fSStefano Zampini   if (matis->A->symmetric_set) {
39723301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3973e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39743301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3975e496cd5dSStefano Zampini #endif
39763301b35fSStefano Zampini   }
3977d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3978aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3979aa0d41d4SStefano Zampini }
3980aa0d41d4SStefano Zampini 
3981aa0d41d4SStefano Zampini #undef __FUNCT__
3982a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
39838ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3984a64d13efSStefano Zampini {
3985a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3986a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3987d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
398853892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
39893a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
39903a50541eSStefano Zampini   PetscInt        vbs,bs;
39916816873aSStefano Zampini   PetscBT         bitmask=NULL;
3992a64d13efSStefano Zampini   PetscErrorCode  ierr;
3993a64d13efSStefano Zampini 
3994a64d13efSStefano Zampini   PetscFunctionBegin;
3995b23d619eSStefano Zampini   /*
3996b23d619eSStefano Zampini     No need to setup local scatters if
3997b23d619eSStefano Zampini       - primal space is unchanged
3998b23d619eSStefano Zampini         AND
3999b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4000b23d619eSStefano Zampini         AND
4001b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4002b23d619eSStefano Zampini   */
4003b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4004f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4005f4ddd8eeSStefano Zampini   }
4006f4ddd8eeSStefano Zampini   /* destroy old objects */
4007f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4008f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4009f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4010a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4011b371cd4fSStefano Zampini   n_B = pcis->n_B;
4012b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4013b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
40143a50541eSStefano Zampini 
4015a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
40166816873aSStefano Zampini 
401753892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4018b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4019854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4020a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4021a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
40220e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4023a64d13efSStefano Zampini     }
4024a64d13efSStefano Zampini 
4025a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
40264641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
40276816873aSStefano Zampini         idx_R_local[n_R++] = i;
4028a64d13efSStefano Zampini       }
4029a64d13efSStefano Zampini     }
4030df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4031df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
40326816873aSStefano Zampini 
4033df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4034df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
40356816873aSStefano Zampini   }
40363a50541eSStefano Zampini 
40373a50541eSStefano Zampini   /* Block code */
40383a50541eSStefano Zampini   vbs = 1;
40393a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
40403a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
40413a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
40423a50541eSStefano Zampini     PetscInt  *vary;
4043b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4044785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
40453a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4046d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4047d3df7717SStefano 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 */
40480e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4049d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
40503a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
40513a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
40523a50541eSStefano Zampini           break;
40533a50541eSStefano Zampini         }
40543a50541eSStefano Zampini       }
4055d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4056d3df7717SStefano Zampini     } else {
4057d3df7717SStefano Zampini       /* Verify directly the R set */
4058d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4059d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4060d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4061d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4062d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4063d3df7717SStefano Zampini             break;
4064d3df7717SStefano Zampini           }
4065d3df7717SStefano Zampini         }
4066d3df7717SStefano Zampini       }
4067d3df7717SStefano Zampini     }
40683a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
40693a50541eSStefano Zampini       vbs = bs;
40703a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
40713a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
40723a50541eSStefano Zampini       }
40733a50541eSStefano Zampini     }
40743a50541eSStefano Zampini   }
40753a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4076b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4077df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
407853892102SStefano Zampini 
4079df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4080df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
408153892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4082df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
408353892102SStefano Zampini   } else {
40843a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
408553892102SStefano Zampini   }
4086a64d13efSStefano Zampini 
4087a64d13efSStefano Zampini   /* print some info if requested */
4088a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4089a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4090a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40911575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4092a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4093a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
40944f1b2e48SStefano 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);
4095a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4096a64d13efSStefano Zampini   }
4097a64d13efSStefano Zampini 
4098a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4099b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
41006816873aSStefano Zampini     IS       is_aux1,is_aux2;
41016816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
41026816873aSStefano Zampini 
41033a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4104854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4105854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4106a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
41074641a718SStefano Zampini     for (i=0; i<n_D; i++) {
41084641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
41094641a718SStefano Zampini     }
4110a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4111a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
41124641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
41134641a718SStefano Zampini         aux_array1[j++] = i;
4114a64d13efSStefano Zampini       }
4115a64d13efSStefano Zampini     }
4116a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4117a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4118a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
41194641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
41204641a718SStefano Zampini         aux_array2[j++] = i;
4121a64d13efSStefano Zampini       }
4122a64d13efSStefano Zampini     }
4123a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4124a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4125a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4126a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4127a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4128a64d13efSStefano Zampini 
41298eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4130785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4131a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
41324641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
41334641a718SStefano Zampini           aux_array1[j++] = i;
4134a64d13efSStefano Zampini         }
4135a64d13efSStefano Zampini       }
4136a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4137a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4138a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4139a64d13efSStefano Zampini     }
41404641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
41413a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4142d62866d3SStefano Zampini   } else {
4143df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
41446816873aSStefano Zampini     IS                 tis;
41456816873aSStefano Zampini     PetscInt           schur_size;
41466816873aSStefano Zampini 
4147df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
41486816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4149df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
41506816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
41516816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41526816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
41536816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
41546816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4155d62866d3SStefano Zampini     }
4156d62866d3SStefano Zampini   }
4157a64d13efSStefano Zampini   PetscFunctionReturn(0);
4158a64d13efSStefano Zampini }
4159a64d13efSStefano Zampini 
4160304d26faSStefano Zampini 
4161304d26faSStefano Zampini #undef __FUNCT__
4162304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4163684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4164304d26faSStefano Zampini {
4165304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4166304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4167304d26faSStefano Zampini   PC             pc_temp;
4168304d26faSStefano Zampini   Mat            A_RR;
4169f4ddd8eeSStefano Zampini   MatReuse       reuse;
4170304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4171304d26faSStefano Zampini   PetscReal      value;
417204708bb6SStefano Zampini   PetscInt       n_D,n_R;
4173c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4174304d26faSStefano Zampini   PetscErrorCode ierr;
4175e604994aSStefano Zampini   /* prefixes stuff */
4176312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4177e604994aSStefano Zampini   size_t         len;
4178304d26faSStefano Zampini 
4179304d26faSStefano Zampini   PetscFunctionBegin;
4180304d26faSStefano Zampini 
4181e604994aSStefano Zampini   /* compute prefixes */
4182e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4183e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4184e604994aSStefano Zampini   if (!pcbddc->current_level) {
4185e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4186e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4187e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4188e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4189e604994aSStefano Zampini   } else {
4190e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4191312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4192e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4193e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4194312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4195312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
419634d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
419734d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4198e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4199e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4200e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4201e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4202e604994aSStefano Zampini   }
4203e604994aSStefano Zampini 
4204304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4205684f6988SStefano Zampini   if (dirichlet) {
4206d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4207450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
42089a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4209450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4210a3df083aSStefano Zampini         Mat    A_IIn;
4211a3df083aSStefano Zampini 
4212a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4213a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4214a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4215a3df083aSStefano Zampini       }
4216450f8f5eSStefano Zampini     }
42173301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
42183301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4219964fefecSStefano Zampini     }
4220ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4221964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4222304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4223304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4224304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4225304d26faSStefano Zampini       /* default */
4226304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4227e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
42289577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4229304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
42309577ea80SStefano Zampini       if (issbaij) {
42319577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
42329577ea80SStefano Zampini       } else {
4233304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
42349577ea80SStefano Zampini       }
4235304d26faSStefano Zampini       /* Allow user's customization */
4236304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4237304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4238304d26faSStefano Zampini     }
4239d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4240b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4241df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4242d62866d3SStefano Zampini 
4243df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4244d5574798SStefano Zampini     }
4245304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4246304d26faSStefano Zampini     if (!n_D) {
4247304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4248304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4249304d26faSStefano Zampini     }
4250304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4251304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4252304d26faSStefano Zampini     /* set ksp_D into pcis data */
4253304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4254304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4255304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4256684f6988SStefano Zampini   }
4257304d26faSStefano Zampini 
4258304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4259684f6988SStefano Zampini   A_RR = 0;
4260684f6988SStefano Zampini   if (neumann) {
4261d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
426204708bb6SStefano Zampini     PetscInt        ibs,mbs;
426304708bb6SStefano Zampini     PetscBool       issbaij;
426404708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4265f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
42668ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4267f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4268f4ddd8eeSStefano Zampini       PetscInt nn_R;
426981d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4270f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4271f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4272f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4273f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4274f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4275f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4276f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4277727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4278f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4279f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4280f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4281f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4282f4ddd8eeSStefano Zampini         }
4283f4ddd8eeSStefano Zampini       }
4284f4ddd8eeSStefano Zampini       /* last check */
4285d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4286f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4287f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4288f4ddd8eeSStefano Zampini       }
4289f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4290f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4291f4ddd8eeSStefano Zampini     }
4292a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4293af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4294af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
429504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
429604708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
429704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
429804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
429904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4300af732b37SStefano Zampini       } else {
4301511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
43026816873aSStefano Zampini       }
430304708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
430404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
430504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
430604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
430704708bb6SStefano Zampini       } else {
4308511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
430904708bb6SStefano Zampini       }
431004708bb6SStefano Zampini     }
4311a00504b5SStefano Zampini     /* extract A_RR */
4312b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4313a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4314a00504b5SStefano Zampini 
4315a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
431616e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4317a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
431816e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
431916e386b8SStefano Zampini         } else {
4320a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4321a00504b5SStefano Zampini         }
4322a00504b5SStefano Zampini       } else {
4323a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4324a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4325a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4326a00504b5SStefano Zampini       }
4327a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4328f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
432916e386b8SStefano Zampini     }
43303301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
43313301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
43326816873aSStefano Zampini     }
4333f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4334304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4335304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4336304d26faSStefano Zampini       /* default */
4337304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4338e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4339304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
43409577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
43419577ea80SStefano Zampini       if (issbaij) {
43429577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
43439577ea80SStefano Zampini       } else {
4344304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
43459577ea80SStefano Zampini       }
4346304d26faSStefano Zampini       /* Allow user's customization */
4347304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4348304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4349304d26faSStefano Zampini     }
4350304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4351304d26faSStefano Zampini     if (!n_R) {
4352304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4353304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4354304d26faSStefano Zampini     }
43555cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4356df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4357b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4358df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4359d62866d3SStefano Zampini 
4360df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4361d62866d3SStefano Zampini     }
4362304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4363304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4364684f6988SStefano Zampini   }
4365304d26faSStefano Zampini 
4366684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4367684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43681575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4369684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4370684f6988SStefano Zampini   }
4371c7017625SStefano Zampini 
4372c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4373c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4374c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4375c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4376c7017625SStefano Zampini   }
4377c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4378c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4379c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4380c7017625SStefano Zampini   }
4381c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4382c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4383c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4384c7017625SStefano Zampini   }
4385c7017625SStefano Zampini 
4386c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4387c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4388684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
43890fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
43900fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
43910fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
43920fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
43930fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4394e604994aSStefano 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);
4395c7017625SStefano Zampini       if (check_corr[0]) {
4396c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4397c7017625SStefano Zampini       }
4398304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4399304d26faSStefano Zampini     }
4400684f6988SStefano Zampini     if (neumann) { /* Neumann */
44010fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
44020fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
44030fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
44040fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
44050fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4406e604994aSStefano 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);
4407c7017625SStefano Zampini       if (check_corr[1]) {
4408c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4409c7017625SStefano Zampini       }
4410304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4411304d26faSStefano Zampini     }
4412684f6988SStefano Zampini   }
44135cbda25cSStefano Zampini   /* free Neumann problem's matrix */
44145cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4415304d26faSStefano Zampini   PetscFunctionReturn(0);
4416304d26faSStefano Zampini }
4417304d26faSStefano Zampini 
4418304d26faSStefano Zampini #undef __FUNCT__
4419ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
442080677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4421674ae819SStefano Zampini {
4422674ae819SStefano Zampini   PetscErrorCode  ierr;
4423674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4424be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4425b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4426674ae819SStefano Zampini 
4427674ae819SStefano Zampini   PetscFunctionBegin;
4428b334f244SStefano Zampini   if (!reuse_solver) {
442980677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
443020c7b377SStefano Zampini   }
443180677318SStefano Zampini   if (!pcbddc->switch_static) {
443280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
443380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
443480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
443520c7b377SStefano Zampini     }
4436b334f244SStefano Zampini     if (!reuse_solver) {
443780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
443880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
443920c7b377SStefano Zampini     } else {
4440df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4441be83ff47SStefano Zampini 
4442df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4443df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
444420c7b377SStefano Zampini     }
4445be83ff47SStefano Zampini   } else {
444680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
445180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
445280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
445380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4455674ae819SStefano Zampini     }
4456674ae819SStefano Zampini   }
4457b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
445880677318SStefano Zampini     if (applytranspose) {
445980677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446080677318SStefano Zampini     } else {
446180677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446280677318SStefano Zampini     }
4463be83ff47SStefano Zampini   } else {
4464df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4465be83ff47SStefano Zampini 
4466be83ff47SStefano Zampini     if (applytranspose) {
4467df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4468be83ff47SStefano Zampini     } else {
4469df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4470be83ff47SStefano Zampini     }
4471be83ff47SStefano Zampini   }
447280677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
447380677318SStefano Zampini   if (!pcbddc->switch_static) {
4474b334f244SStefano Zampini     if (!reuse_solver) {
447580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
447680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4477be83ff47SStefano Zampini     } else {
4478df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4479be83ff47SStefano Zampini 
4480df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4481df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4482be83ff47SStefano Zampini     }
448380677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
448480677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
448580677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
448680677318SStefano Zampini     }
448780677318SStefano Zampini   } else {
448880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
449380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
449480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
449580677318SStefano Zampini     }
449680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4500674ae819SStefano Zampini   }
4501674ae819SStefano Zampini   PetscFunctionReturn(0);
4502674ae819SStefano Zampini }
4503674ae819SStefano Zampini 
4504dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4505674ae819SStefano Zampini #undef __FUNCT__
4506674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4507dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4508674ae819SStefano Zampini {
4509674ae819SStefano Zampini   PetscErrorCode ierr;
4510674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4511674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4512674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4513674ae819SStefano Zampini 
4514674ae819SStefano Zampini   PetscFunctionBegin;
4515dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
45164fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4517dc359a40SStefano Zampini     if (applytranspose) {
4518674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
45198eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4520dc359a40SStefano Zampini     } else {
4521674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4522674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
452315aaf578SStefano Zampini     }
45244fee134fSStefano Zampini   } else {
45254fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
45264fee134fSStefano Zampini   }
4527efc2fbd9SStefano Zampini 
4528efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
45294f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4530efc2fbd9SStefano Zampini     PetscScalar *array;
45314f1b2e48SStefano Zampini     PetscInt    j;
4532efc2fbd9SStefano Zampini 
4533efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
45344f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4535efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4536efc2fbd9SStefano Zampini   }
4537efc2fbd9SStefano Zampini 
453812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
453912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
454012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454212edc857SStefano Zampini 
45439f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
454412edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
454551694757SStefano Zampini     Mat          coarse_mat;
4546964fefecSStefano Zampini     Vec          rhs,sol;
454751694757SStefano Zampini     MatNullSpace nullsp;
454827b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4549964fefecSStefano Zampini 
455027b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
455127b6a85dSStefano Zampini       PC        coarse_pc;
455227b6a85dSStefano Zampini 
455327b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
455427b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
455527b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
455627b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
455727b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
455827b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
45593bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
456027b6a85dSStefano Zampini       }
456127b6a85dSStefano Zampini     }
4562964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4563964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
456451694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
456551694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
456651694757SStefano Zampini     if (nullsp) {
456751694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
456851694757SStefano Zampini     }
456912edc857SStefano Zampini     if (applytranspose) {
45709a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4571964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
45722701bc32SStefano Zampini     } else {
45731f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
45742701bc32SStefano Zampini         PC        coarse_pc;
45752701bc32SStefano Zampini 
45762701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
45772701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
45783e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
45792701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
458012edc857SStefano Zampini       } else {
4581964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
458212edc857SStefano Zampini       }
45832701bc32SStefano Zampini     }
45841d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
458527b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
458627b6a85dSStefano Zampini       PC        coarse_pc;
458727b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
458827b6a85dSStefano Zampini 
458927b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
459027b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
459127b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
45923bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
459327b6a85dSStefano Zampini     }
459451694757SStefano Zampini     if (nullsp) {
459551694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
459651694757SStefano Zampini     }
459712edc857SStefano Zampini   }
4598674ae819SStefano Zampini 
4599674ae819SStefano Zampini   /* Local solution on R nodes */
46004fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
460180677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
46029f00e9b4SStefano Zampini   }
46039f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
46049f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
460512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4606674ae819SStefano Zampini 
46074fee134fSStefano Zampini   /* Sum contributions from the two levels */
46084fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4609dc359a40SStefano Zampini     if (applytranspose) {
4610dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4611dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4612dc359a40SStefano Zampini     } else {
4613674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
46148eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4615dc359a40SStefano Zampini     }
4616efc2fbd9SStefano Zampini     /* store p0 */
46174f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4618efc2fbd9SStefano Zampini       PetscScalar *array;
46194f1b2e48SStefano Zampini       PetscInt    j;
4620efc2fbd9SStefano Zampini 
4621efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
46224f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4623efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4624efc2fbd9SStefano Zampini     }
46254fee134fSStefano Zampini   } else { /* expand the coarse solution */
46264fee134fSStefano Zampini     if (applytranspose) {
46274fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46284fee134fSStefano Zampini     } else {
46294fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46304fee134fSStefano Zampini     }
46314fee134fSStefano Zampini   }
4632674ae819SStefano Zampini   PetscFunctionReturn(0);
4633674ae819SStefano Zampini }
4634674ae819SStefano Zampini 
4635674ae819SStefano Zampini #undef __FUNCT__
4636674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
463712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4638674ae819SStefano Zampini {
4639674ae819SStefano Zampini   PetscErrorCode ierr;
4640674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
464158da7f69SStefano Zampini   PetscScalar    *array;
464212edc857SStefano Zampini   Vec            from,to;
4643674ae819SStefano Zampini 
4644674ae819SStefano Zampini   PetscFunctionBegin;
464512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
464612edc857SStefano Zampini     from = pcbddc->coarse_vec;
464712edc857SStefano Zampini     to = pcbddc->vec1_P;
464812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
464912edc857SStefano Zampini       Vec tvec;
465058da7f69SStefano Zampini 
465158da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465258da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
465312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465458da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
465558da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
465658da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
465712edc857SStefano Zampini     }
465812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
465912edc857SStefano Zampini     from = pcbddc->vec1_P;
466012edc857SStefano Zampini     to = pcbddc->coarse_vec;
466112edc857SStefano Zampini   }
466212edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4663674ae819SStefano Zampini   PetscFunctionReturn(0);
4664674ae819SStefano Zampini }
4665674ae819SStefano Zampini 
4666674ae819SStefano Zampini #undef __FUNCT__
4667674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
466812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4669674ae819SStefano Zampini {
4670674ae819SStefano Zampini   PetscErrorCode ierr;
4671674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
467258da7f69SStefano Zampini   PetscScalar    *array;
467312edc857SStefano Zampini   Vec            from,to;
4674674ae819SStefano Zampini 
4675674ae819SStefano Zampini   PetscFunctionBegin;
467612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
467712edc857SStefano Zampini     from = pcbddc->coarse_vec;
467812edc857SStefano Zampini     to = pcbddc->vec1_P;
467912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
468012edc857SStefano Zampini     from = pcbddc->vec1_P;
468112edc857SStefano Zampini     to = pcbddc->coarse_vec;
468212edc857SStefano Zampini   }
468312edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
468412edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
468512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
468612edc857SStefano Zampini       Vec tvec;
468758da7f69SStefano Zampini 
468812edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
468958da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
469058da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
469158da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
469258da7f69SStefano Zampini     }
469358da7f69SStefano Zampini   } else {
469458da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
469558da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
469612edc857SStefano Zampini     }
469712edc857SStefano Zampini   }
4698674ae819SStefano Zampini   PetscFunctionReturn(0);
4699674ae819SStefano Zampini }
4700674ae819SStefano Zampini 
4701984c4197SStefano Zampini /* uncomment for testing purposes */
4702984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4703674ae819SStefano Zampini #undef __FUNCT__
4704674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4705674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4706674ae819SStefano Zampini {
4707674ae819SStefano Zampini   PetscErrorCode    ierr;
4708674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4709674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4710674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4711984c4197SStefano Zampini   /* one and zero */
4712984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4713984c4197SStefano Zampini   /* space to store constraints and their local indices */
47149162d606SStefano Zampini   PetscScalar       *constraints_data;
47159162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
47169162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
47179162d606SStefano Zampini   PetscInt          *constraints_n;
4718984c4197SStefano Zampini   /* iterators */
4719b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4720984c4197SStefano Zampini   /* BLAS integers */
4721e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4722e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4723c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4724727cdba6SStefano Zampini   /* reuse */
47250e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
47260e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4727984c4197SStefano Zampini   /* change of basis */
4728b3d85658SStefano Zampini   PetscBool         qr_needed;
47299162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4730984c4197SStefano Zampini   /* auxiliary stuff */
473164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
47328a0068c3SStefano Zampini   PetscInt          ncc;
4733984c4197SStefano Zampini   /* some quantities */
473445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4735a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4736984c4197SStefano Zampini 
4737674ae819SStefano Zampini   PetscFunctionBegin;
47388e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
47398e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47408e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
474116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4742088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4743088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
47440e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
47450e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
47460e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47470e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47480e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4749088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4750cf5a6209SStefano Zampini 
4751cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
47529162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4753cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4754cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4755cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4756cf5a6209SStefano Zampini     PetscScalar  *array;
4757cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4758cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4759674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4760b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4761674ae819SStefano Zampini     PetscScalar  *work;
4762674ae819SStefano Zampini     PetscReal    *singular_vals;
4763674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4764674ae819SStefano Zampini     PetscReal    *rwork;
4765674ae819SStefano Zampini #endif
4766674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4767674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4768674ae819SStefano Zampini #else
4769964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4770964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4771674ae819SStefano Zampini #endif
4772674ae819SStefano Zampini 
4773674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4774d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4775e4d548c7SStefano Zampini     /* print some info */
47761f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4777e4d548c7SStefano Zampini       PetscInt nv;
4778e4d548c7SStefano Zampini 
4779c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4780e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4781e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4782e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4783e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4784e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4785e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4786e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4787e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4788e4d548c7SStefano Zampini     }
4789e4d548c7SStefano Zampini 
4790d06fc5fdSStefano Zampini     /* free unneeded index sets */
4791d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4792d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4793674ae819SStefano Zampini     }
4794d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4795d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4796d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4797d06fc5fdSStefano Zampini       }
4798d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4799d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4800d06fc5fdSStefano Zampini     }
4801d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4802d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4803d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4804d06fc5fdSStefano Zampini       }
4805d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4806d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4807d06fc5fdSStefano Zampini     }
480870022509SStefano Zampini 
4809674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4810674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4811674ae819SStefano Zampini     if (nearnullsp) {
4812674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4813f4ddd8eeSStefano Zampini       /* remove any stored info */
4814f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4815f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4816f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4817f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4818f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4819473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4820f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4821f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4822f4ddd8eeSStefano Zampini       }
4823984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4824984c4197SStefano Zampini       nnsp_size = 0;
4825674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4826674ae819SStefano Zampini     }
4827984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4828984c4197SStefano Zampini     max_constraints = nnsp_size;
4829984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4830984c4197SStefano Zampini 
4831674ae819SStefano Zampini     /*
4832674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
48339162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
48349162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
48359162d606SStefano Zampini          There can be multiple constraints per connected component
4836674ae819SStefano Zampini                                                                                                                                                            */
4837674ae819SStefano Zampini     n_vertices = 0;
4838674ae819SStefano Zampini     if (ISForVertices) {
4839674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4840674ae819SStefano Zampini     }
48419162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
48429162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
48439162d606SStefano Zampini 
48449162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
48459162d606SStefano Zampini     total_counts *= max_constraints;
4846674ae819SStefano Zampini     total_counts += n_vertices;
48474641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
48489162d606SStefano Zampini 
4849674ae819SStefano Zampini     total_counts = 0;
4850674ae819SStefano Zampini     max_size_of_constraint = 0;
4851674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
48529162d606SStefano Zampini       IS used_is;
4853674ae819SStefano Zampini       if (i<n_ISForEdges) {
48549162d606SStefano Zampini         used_is = ISForEdges[i];
4855674ae819SStefano Zampini       } else {
48569162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4857674ae819SStefano Zampini       }
48589162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4859674ae819SStefano Zampini       total_counts += j;
4860674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4861674ae819SStefano Zampini     }
48629162d606SStefano 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);
48639162d606SStefano Zampini 
4864984c4197SStefano Zampini     /* get local part of global near null space vectors */
4865785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4866984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4867984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4868e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4869e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4870984c4197SStefano Zampini     }
4871674ae819SStefano Zampini 
4872242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4873242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4874a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4875242a89d7SStefano Zampini 
4876984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4877a773dcb8SStefano Zampini     if (!skip_lapack) {
4878674ae819SStefano Zampini       PetscScalar temp_work;
4879911cabfeSStefano Zampini 
4880674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4881984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4882785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4883785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4884785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4885674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4886785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4887674ae819SStefano Zampini #endif
4888674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4889c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4890c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4891674ae819SStefano Zampini       lwork = -1;
4892674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4893674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4894c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4895674ae819SStefano Zampini #else
4896c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4897674ae819SStefano Zampini #endif
4898674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4899984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4900674ae819SStefano Zampini #else /* on missing GESVD */
4901674ae819SStefano Zampini       /* SVD */
4902674ae819SStefano Zampini       PetscInt max_n,min_n;
4903674ae819SStefano Zampini       max_n = max_size_of_constraint;
4904984c4197SStefano Zampini       min_n = max_constraints;
4905984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4906674ae819SStefano Zampini         min_n = max_size_of_constraint;
4907984c4197SStefano Zampini         max_n = max_constraints;
4908674ae819SStefano Zampini       }
4909785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4910674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4911785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4912674ae819SStefano Zampini #endif
4913674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4914674ae819SStefano Zampini       lwork = -1;
4915e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4916e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4917b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4918674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4919674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
49209162d606SStefano 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));
4921674ae819SStefano Zampini #else
49229162d606SStefano 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));
4923674ae819SStefano Zampini #endif
4924674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4925984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4926984c4197SStefano Zampini #endif /* on missing GESVD */
4927674ae819SStefano Zampini       /* Allocate optimal workspace */
4928674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4929854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4930674ae819SStefano Zampini     }
4931674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4932674ae819SStefano Zampini     total_counts = 0;
49339162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
49349162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4935674ae819SStefano Zampini     /* vertices */
49369162d606SStefano Zampini     if (n_vertices) {
4937674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
49389162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4939674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
49409162d606SStefano Zampini         constraints_n[total_counts] = 1;
49419162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
49429162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
49439162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4944674ae819SStefano Zampini         total_counts++;
4945674ae819SStefano Zampini       }
4946674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4947674ae819SStefano Zampini       n_vertices = total_counts;
4948674ae819SStefano Zampini     }
4949984c4197SStefano Zampini 
4950674ae819SStefano Zampini     /* edges and faces */
49519162d606SStefano Zampini     total_counts_cc = total_counts;
4952911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
49539162d606SStefano Zampini       IS        used_is;
49549162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
49559162d606SStefano Zampini 
4956911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
49579162d606SStefano Zampini         used_is = ISForEdges[ncc];
4958984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4959674ae819SStefano Zampini       } else {
49609162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4961984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4962674ae819SStefano Zampini       }
4963674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
49649162d606SStefano Zampini 
49659162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
49669162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4967984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4968984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4969674ae819SStefano Zampini       if (nnsp_has_cnst) {
49705b08dc53SStefano Zampini         PetscScalar quad_value;
49719162d606SStefano Zampini 
49729162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
49739162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
49749162d606SStefano Zampini 
4975a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4976674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4977a773dcb8SStefano Zampini         } else {
4978a773dcb8SStefano Zampini           quad_value = 1.0;
4979a773dcb8SStefano Zampini         }
4980674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49819162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4982674ae819SStefano Zampini         }
49839162d606SStefano Zampini         temp_constraints++;
4984674ae819SStefano Zampini         total_counts++;
4985674ae819SStefano Zampini       }
4986674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4987984c4197SStefano Zampini         PetscReal real_value;
49889162d606SStefano Zampini         PetscScalar *ptr_to_data;
49899162d606SStefano Zampini 
4990984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
49919162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4992674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49939162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4994674ae819SStefano Zampini         }
4995984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
4996984c4197SStefano Zampini         /* check if array is null on the connected component */
4997e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
49989162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
49995b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5000674ae819SStefano Zampini           temp_constraints++;
5001674ae819SStefano Zampini           total_counts++;
50029162d606SStefano Zampini           if (!idxs_copied) {
50039162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
50049162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5005674ae819SStefano Zampini           }
5006674ae819SStefano Zampini         }
50079162d606SStefano Zampini       }
50089162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
500945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5010eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5011a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
50129162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
50139162d606SStefano Zampini 
50149162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5015a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
50169162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5017a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
50189162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5019a773dcb8SStefano Zampini         } else { /* perform SVD */
5020984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
50219162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5022674ae819SStefano Zampini 
5023674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5024984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5025984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5026984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5027984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5028984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5029984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5030984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5031984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5032674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5033e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5034984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5035674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5036674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
50379162d606SStefano 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));
5038674ae819SStefano Zampini             }
5039674ae819SStefano Zampini           }
5040e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5041e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5042e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5043674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5044c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5045674ae819SStefano Zampini #else
5046c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5047674ae819SStefano Zampini #endif
5048674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5049984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5050984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5051674ae819SStefano Zampini           j = 0;
5052984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5053674ae819SStefano Zampini           total_counts = total_counts-j;
505445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5055e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5056c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5057c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5058c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5059c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5060c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5061c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5062674ae819SStefano Zampini           if (j<temp_constraints) {
5063984c4197SStefano Zampini             PetscInt ii;
5064984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5065674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50669162d606SStefano 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));
5067674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5068984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5069674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
50709162d606SStefano 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];
5071674ae819SStefano Zampini               }
5072674ae819SStefano Zampini             }
5073674ae819SStefano Zampini           }
5074674ae819SStefano Zampini #else  /* on missing GESVD */
5075e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5076e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5077b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5078674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5079674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
50809162d606SStefano 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));
5081674ae819SStefano Zampini #else
50829162d606SStefano 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));
5083674ae819SStefano Zampini #endif
5084984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5085674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5086984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5087e310c8b4SStefano Zampini           k = temp_constraints;
5088e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5089674ae819SStefano Zampini           j = 0;
5090e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
509145a1bb75SStefano Zampini           valid_constraints = k-j;
5092911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5093984c4197SStefano Zampini #endif /* on missing GESVD */
5094674ae819SStefano Zampini         }
5095a773dcb8SStefano Zampini       }
50969162d606SStefano Zampini       /* update pointers information */
50979162d606SStefano Zampini       if (valid_constraints) {
50989162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
50999162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
51009162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
51019162d606SStefano Zampini         /* set change_of_basis flag */
510245a1bb75SStefano Zampini         if (boolforchange) {
5103b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
51049162d606SStefano Zampini         }
5105b3d85658SStefano Zampini         total_counts_cc++;
510645a1bb75SStefano Zampini       }
510745a1bb75SStefano Zampini     }
5108984c4197SStefano Zampini     /* free workspace */
51098f1c130eSStefano Zampini     if (!skip_lapack) {
5110984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5111984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5112984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5113984c4197SStefano Zampini #endif
5114984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5115984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5116984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5117984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5118984c4197SStefano Zampini #endif
5119984c4197SStefano Zampini     }
5120984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5121984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5122984c4197SStefano Zampini     }
5123984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5124cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5125cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5126cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5127cf5a6209SStefano Zampini     }
5128cf5a6209SStefano Zampini     if (n_ISForFaces) {
5129cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5130cf5a6209SStefano Zampini     }
5131cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5132cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5133cf5a6209SStefano Zampini     }
5134cf5a6209SStefano Zampini     if (n_ISForEdges) {
5135cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5136cf5a6209SStefano Zampini     }
5137cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
513808122e43SStefano Zampini   } else {
513908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5140984c4197SStefano Zampini 
514108122e43SStefano Zampini     total_counts = 0;
514208122e43SStefano Zampini     n_vertices = 0;
5143d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5144d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
514508122e43SStefano Zampini     }
514608122e43SStefano Zampini     max_constraints = 0;
51479162d606SStefano Zampini     total_counts_cc = 0;
514808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
514908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
51509162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
515108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
515208122e43SStefano Zampini     }
51539162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
51549162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
51559162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
51569162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
515774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
51589162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
51599162d606SStefano Zampini     total_counts_cc = 0;
51609162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
51619162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
51629162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
516308122e43SStefano Zampini       }
516408122e43SStefano Zampini     }
51659162d606SStefano Zampini #if 0
51669162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
51679162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
51689162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
51699162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
51709162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
51719162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
51729162d606SStefano Zampini       }
51739162d606SStefano Zampini       printf("\n");
51749162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
51759162d606SStefano Zampini     }
51761b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
51778bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
51781b968477SStefano Zampini     }
51791b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
51808bec7fa6SStefano 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]);
51811b968477SStefano Zampini     }
518208122e43SStefano Zampini #endif
518308122e43SStefano Zampini 
51848bec7fa6SStefano Zampini     max_size_of_constraint = 0;
51859162d606SStefano 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]);
51869162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
518708122e43SStefano Zampini     /* Change of basis */
5188b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
518908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
519008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
519108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5192b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
519308122e43SStefano Zampini         }
519408122e43SStefano Zampini       }
519508122e43SStefano Zampini     }
519608122e43SStefano Zampini   }
5197984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
51984f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
519908122e43SStefano Zampini 
52009162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
52019162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
52026c4ed002SBarry 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);
5203674ae819SStefano Zampini 
5204674ae819SStefano Zampini   /* Create constraint matrix */
5205674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
520616f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5207984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5208984c4197SStefano Zampini 
5209984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5210a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5211a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
521274d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5213984c4197SStefano Zampini   total_primal_vertices=0;
5214b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
52159162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
52169162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
521772b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
52189162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5219b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
522064efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
52219162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52229162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5223a717540cSStefano Zampini       }
5224b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
522591af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5226a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5227a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5228a717540cSStefano Zampini       }
5229fa434743SStefano Zampini     } else {
5230b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5231fa434743SStefano Zampini     }
5232a717540cSStefano Zampini   }
5233b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5234b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5235674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
523670022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5237b3d85658SStefano Zampini 
52384f1b2e48SStefano 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);
52390e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
52400e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5241984c4197SStefano Zampini 
5242984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
524374d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5244785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5245984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
524674d5cdf7SStefano Zampini 
5247984c4197SStefano Zampini   j = total_primal_vertices;
524874d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5249b3d85658SStefano Zampini   cum = total_primal_vertices;
52509162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52514641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5252b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5253b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5254b3d85658SStefano Zampini       cum++;
52559162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
525674d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
525774d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
525874d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
525974d5cdf7SStefano Zampini       }
52609162d606SStefano Zampini       j += constraints_n[i];
5261674ae819SStefano Zampini     }
5262674ae819SStefano Zampini   }
5263674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5264674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5265088faed8SStefano Zampini 
5266674ae819SStefano Zampini   /* set values in constraint matrix */
5267984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
52680e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5269674ae819SStefano Zampini   }
5270984c4197SStefano Zampini   total_counts = total_primal_vertices;
52719162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52724641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
52739162d606SStefano Zampini       PetscInt *cols;
52749162d606SStefano Zampini 
52759162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
52769162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
52779162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52789162d606SStefano Zampini         PetscInt    row = total_counts+k;
52799162d606SStefano Zampini         PetscScalar *vals;
52809162d606SStefano Zampini 
52819162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
52829162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
52839162d606SStefano Zampini       }
52849162d606SStefano Zampini       total_counts += constraints_n[i];
5285674ae819SStefano Zampini     }
5286674ae819SStefano Zampini   }
5287674ae819SStefano Zampini   /* assembling */
5288674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5289674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5290088faed8SStefano Zampini 
5291984c4197SStefano Zampini   /*
52926a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5293984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5294f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5295984c4197SStefano Zampini   */
5296674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5297674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5298026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5299984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5300984c4197SStefano Zampini     /* working stuff for GEQRF */
530181d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5302984c4197SStefano Zampini     PetscBLASInt lqr_work;
5303984c4197SStefano Zampini     /* working stuff for UNGQR */
5304984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5305984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5306984c4197SStefano Zampini     /* working stuff for TRTRS */
5307984c4197SStefano Zampini     PetscScalar  *trs_rhs;
53083f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5309984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5310984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5311984c4197SStefano Zampini     PetscScalar  *start_vals;
5312984c4197SStefano Zampini     /* working stuff for values insertion */
53134641a718SStefano Zampini     PetscBT      is_primal;
531464efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5315906d46d4SStefano Zampini     /* matrix sizes */
5316906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5317906d46d4SStefano Zampini     /* temporary change of basis */
5318906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5319cf5a6209SStefano Zampini     /* extra space for debugging */
5320cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5321984c4197SStefano Zampini 
5322906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5323906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
532416f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5325bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5326906d46d4SStefano Zampini     /* nonzeros for local mat */
5327bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
53281dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5329bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
53301dd7afcfSStefano Zampini     } else {
53311dd7afcfSStefano Zampini       const PetscInt *ii;
53321dd7afcfSStefano Zampini       PetscInt       n;
53331dd7afcfSStefano Zampini       PetscBool      flg_row;
53341dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53351dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
53361dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53371dd7afcfSStefano Zampini     }
53389162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5339a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
53409162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5341a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
53429162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5343a717540cSStefano Zampini         } else {
53449162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
53459162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5346a717540cSStefano Zampini         }
5347a717540cSStefano Zampini       }
5348a717540cSStefano Zampini     }
5349906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5350bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
53511dd7afcfSStefano Zampini     /* Set interior change in the matrix */
53521dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5353bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5354906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5355a717540cSStefano Zampini       }
53561dd7afcfSStefano Zampini     } else {
53571dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
53581dd7afcfSStefano Zampini       PetscScalar    *aa;
53591dd7afcfSStefano Zampini       PetscInt       n;
53601dd7afcfSStefano Zampini       PetscBool      flg_row;
53611dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53621dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53631dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
53641dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
53651dd7afcfSStefano Zampini       }
53661dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53671dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53681dd7afcfSStefano Zampini     }
5369a717540cSStefano Zampini 
5370a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5371a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5372a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5373a717540cSStefano Zampini     }
5374a717540cSStefano Zampini 
5375a717540cSStefano Zampini 
5376a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5377a717540cSStefano Zampini     /*
5378a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5379a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5380a717540cSStefano Zampini 
5381a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5382a717540cSStefano Zampini 
5383a6b551f4SStefano 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)
5384a6b551f4SStefano Zampini 
5385a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5386a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5387a717540cSStefano Zampini             |              ...                        |
5388a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5389a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5390a717540cSStefano Zampini 
5391a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5392a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5393a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5394a6b551f4SStefano Zampini 
5395a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5396a717540cSStefano Zampini     */
5397a717540cSStefano Zampini     if (qr_needed) {
5398984c4197SStefano Zampini       /* space to store Q */
5399854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
54004e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
54014e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5402984c4197SStefano Zampini       /* first we issue queries for optimal work */
54033f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54043f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
54053f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5406984c4197SStefano Zampini       lqr_work = -1;
54073f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5408984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5409984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5410785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5411984c4197SStefano Zampini       lgqr_work = -1;
54123f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54133f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
54143f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
54153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54163f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
54173f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5418984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5419984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5420785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5421984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5422785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5423a717540cSStefano Zampini       /* allocating workspace for check */
5424a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5425cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5426a717540cSStefano Zampini       }
5427a717540cSStefano Zampini     }
5428984c4197SStefano Zampini     /* array to store whether a node is primal or not */
54294641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5430473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
54310e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
54326c4ed002SBarry 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);
543339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
543439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
543539e2fb2aSStefano Zampini     }
543639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5437984c4197SStefano Zampini 
5438a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
54399162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
54409162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
54414641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5442984c4197SStefano Zampini         /* get constraint info */
54439162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5444984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5445984c4197SStefano Zampini 
5446984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
54479162d606SStefano 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);
5448674ae819SStefano Zampini         }
5449984c4197SStefano Zampini 
5450fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5451a717540cSStefano Zampini 
5452a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5453a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
54549162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5455a717540cSStefano Zampini           }
5456984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
54579162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5458984c4197SStefano Zampini 
5459984c4197SStefano Zampini           /* compute QR decomposition of constraints */
54603f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54613f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54623f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5463674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54643f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5465984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5466674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5467984c4197SStefano Zampini 
5468984c4197SStefano Zampini           /* explictly compute R^-T */
5469984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5470984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
54713f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54723f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
54733f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5475984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54763f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5477984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5478984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5479984c4197SStefano Zampini 
5480a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
54813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5485984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54863f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5487984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5488984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5489984c4197SStefano Zampini 
5490984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5491984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5492984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
54933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
54983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5499984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
55009162d606SStefano 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));
5501984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
55029162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5503984c4197SStefano Zampini 
5504984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
55059162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5506984c4197SStefano Zampini           /* insert cols for primal dofs */
5507984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5508984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
55099162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5510906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5511984c4197SStefano Zampini           }
5512984c4197SStefano Zampini           /* insert cols for dual dofs */
5513984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
55149162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5515984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
55169162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5517906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5518984c4197SStefano Zampini               j++;
5519674ae819SStefano Zampini             }
5520674ae819SStefano Zampini           }
5521984c4197SStefano Zampini 
5522984c4197SStefano Zampini           /* check change of basis */
5523984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5524984c4197SStefano Zampini             PetscInt   ii,jj;
5525984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5526c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5527c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5528c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5529c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5530c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5531c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5532984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5533cf5a6209SStefano 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));
5534984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5535984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5536984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5537cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5538cf5a6209SStefano 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;
5539674ae819SStefano Zampini               }
5540674ae819SStefano Zampini             }
5541984c4197SStefano Zampini             if (!valid_qr) {
554222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5543984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5544984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5545cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5546cf5a6209SStefano 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]));
5547674ae819SStefano Zampini                   }
5548cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5549cf5a6209SStefano 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]));
5550984c4197SStefano Zampini                   }
5551984c4197SStefano Zampini                 }
5552984c4197SStefano Zampini               }
5553674ae819SStefano Zampini             } else {
555422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5555674ae819SStefano Zampini             }
5556674ae819SStefano Zampini           }
5557a717540cSStefano Zampini         } else { /* simple transformation block */
5558a717540cSStefano Zampini           PetscInt    row,col;
5559a6b551f4SStefano Zampini           PetscScalar val,norm;
5560a6b551f4SStefano Zampini 
5561a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55629162d606SStefano 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));
5563a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
55649162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
55659162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5566bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
55679162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5568906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
55699162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5570a717540cSStefano Zampini             } else {
5571a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
55729162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5573a717540cSStefano Zampini                 if (row != col) {
55749162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5575a717540cSStefano Zampini                 } else {
55769162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5577a717540cSStefano Zampini                 }
5578906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5579a717540cSStefano Zampini               }
5580a717540cSStefano Zampini             }
5581a717540cSStefano Zampini           }
558298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
558322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5584a717540cSStefano Zampini           }
5585674ae819SStefano Zampini         }
5586984c4197SStefano Zampini       } else {
5587984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
55889162d606SStefano 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);
5589674ae819SStefano Zampini         }
5590674ae819SStefano Zampini       }
5591674ae819SStefano Zampini     }
5592a717540cSStefano Zampini 
5593a717540cSStefano Zampini     /* free workspace */
5594a717540cSStefano Zampini     if (qr_needed) {
5595984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5596cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5597984c4197SStefano Zampini       }
5598984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5599984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5600984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5601984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5602984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5603674ae819SStefano Zampini     }
5604a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5605906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5606906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5607906d46d4SStefano Zampini 
5608906d46d4SStefano Zampini     /* assembling of global change of variable */
560988c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5610bbb9e6c6SStefano Zampini       Mat      tmat;
561116f15bc4SStefano Zampini       PetscInt bs;
561216f15bc4SStefano Zampini 
5613906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5614906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5615bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5616bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5617bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5618bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
561916f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
562016f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5621906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5622bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5623bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5624bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5625bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5626bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5627e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5628e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5629bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5630bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
563188c03ad3SStefano Zampini 
5632906d46d4SStefano Zampini       /* check */
5633906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5634906d46d4SStefano Zampini         PetscReal error;
5635906d46d4SStefano Zampini         Vec       x,x_change;
5636906d46d4SStefano Zampini 
5637906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5638906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5639906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5640906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5641e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5642e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5643bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5644e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5645e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5646906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5647906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5648906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5649906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5650bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5651906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5652906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5653906d46d4SStefano Zampini       }
5654b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5655b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5656b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5657bf3a8328SStefano Zampini 
56589a962809SStefano 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);
5659b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5660ac632422SStefano Zampini           Mat                    S_new,tmat;
5661bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5662bbb9e6c6SStefano Zampini 
5663bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
56646816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5665bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5666bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5667bf3a8328SStefano Zampini             IS                     is_V;
5668b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5669b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5670b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5671b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5672b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5673bf3a8328SStefano Zampini           }
5674bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5675ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5676b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5677ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5678bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5679bf3a8328SStefano Zampini             const PetscScalar *array;
5680bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5681bf3a8328SStefano Zampini             PetscInt          i,n_V;
5682bf3a8328SStefano Zampini 
5683b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5684b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5685b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5686b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5687b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5688b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5689b087196eSStefano Zampini               PetscScalar val;
5690b087196eSStefano Zampini               PetscInt    idx;
5691b087196eSStefano Zampini 
5692b087196eSStefano Zampini               idx = idxs_V[i];
5693b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5694b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5695b087196eSStefano Zampini             }
5696b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5697b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5698bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5699bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5700bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5701bf3a8328SStefano Zampini           }
5702ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5703ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5704ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5705ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5706b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5707ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5708bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5709b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5710bf3a8328SStefano Zampini             }
5711ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5712ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5713ac632422SStefano Zampini           }
5714b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
571588c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5716b96c3477SStefano Zampini         }
5717c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5718b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5719c9db6a07SStefano Zampini           PetscInt i;
5720c9db6a07SStefano Zampini 
5721c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5722c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5723c9db6a07SStefano Zampini           }
5724c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5725c9db6a07SStefano Zampini         }
5726b96c3477SStefano Zampini       }
572716909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
572816909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
572916909a7fSStefano Zampini       } else {
5730906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
573116909a7fSStefano Zampini       }
57321dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
573327b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
573472b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
573572b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
573672b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
573772b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
573872b8c272SStefano Zampini     }
57391dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
574027b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5741b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5742b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5743906d46d4SStefano Zampini     } else {
57441dd7afcfSStefano Zampini       Mat benign_global = NULL;
574527b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
57461dd7afcfSStefano Zampini         Mat tmat;
57471dd7afcfSStefano Zampini 
57481dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
57491dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
57501dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
57511dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57521dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57531dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
57541dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57551dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57561dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
57571dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
57581dd7afcfSStefano Zampini           Mat M;
57591dd7afcfSStefano Zampini 
57601dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
57611dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
57621dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
57631dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5764906d46d4SStefano Zampini         } else {
57651dd7afcfSStefano Zampini           Mat         eye;
57661dd7afcfSStefano Zampini           PetscScalar *array;
57671dd7afcfSStefano Zampini 
57681dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57691dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
57701dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
57711dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5772906d46d4SStefano Zampini           }
57731dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57741dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57751dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57761dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
57771dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
57781dd7afcfSStefano Zampini         }
57791dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
57801dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
57811dd7afcfSStefano Zampini       }
57821dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
57831dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57841dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
578527b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
57861dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
57871dd7afcfSStefano Zampini       }
57881dd7afcfSStefano Zampini     }
578916909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
579016909a7fSStefano Zampini       IS             is_global;
579116909a7fSStefano Zampini       const PetscInt *gidxs;
579216909a7fSStefano Zampini 
579316909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
579416909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
579516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
579616909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
579716909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
579816909a7fSStefano Zampini     }
57991dd7afcfSStefano Zampini   }
58001dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
58011dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5802b9b85e73SStefano Zampini   }
5803a717540cSStefano Zampini 
580472b8c272SStefano Zampini   if (!pcbddc->fake_change) {
58054f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
58064f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58074f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
58084f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5809019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5810019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5811019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5812019a44ceSStefano Zampini     }
5813019a44ceSStefano Zampini 
5814019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5815727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5816727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
58179f47a83aSStefano 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);
5818c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
58190e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
58209f47a83aSStefano 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);
5821727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5822727cdba6SStefano Zampini       }
58230e6343abSStefano Zampini     }
5824727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5825b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
582672b8c272SStefano Zampini   }
582772b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5828727cdba6SStefano Zampini 
5829a717540cSStefano Zampini   /* flush dbg viewer */
5830b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5831b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5832b8ffe317SStefano Zampini   }
5833a717540cSStefano Zampini 
5834e310c8b4SStefano Zampini   /* free workspace */
5835a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
58364641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
583708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
58389162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
58399162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
584008122e43SStefano Zampini   } else {
58419162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
58429162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
58439162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
584408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
584508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
58469162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
58479162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
584808122e43SStefano Zampini   }
5849674ae819SStefano Zampini   PetscFunctionReturn(0);
5850674ae819SStefano Zampini }
5851674ae819SStefano Zampini 
5852674ae819SStefano Zampini #undef __FUNCT__
5853674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5854674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5855674ae819SStefano Zampini {
585671582508SStefano Zampini   ISLocalToGlobalMapping map;
5857674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5858674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
585914f95afaSStefano Zampini   PetscInt               ierr,i,N;
5860674ae819SStefano Zampini 
5861674ae819SStefano Zampini   PetscFunctionBegin;
5862*c703fcc7SStefano Zampini   if (pcbddc->graphanalyzed) PetscFunctionReturn(0);
58638e61c736SStefano Zampini   /* Reset previously computed graph */
58648e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5865674ae819SStefano Zampini   /* Init local Graph struct */
58667fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
586771582508SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5868be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5869674ae819SStefano Zampini 
5870575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
58719a962809SStefano 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);
58729577ea80SStefano Zampini 
5873674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5874d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
58754d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
58764d379d7bSStefano Zampini     PetscInt  nvtxs;
5877e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
5878674ae819SStefano Zampini 
58792fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
58802fffb893SStefano Zampini     if (flg_row) {
58814d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5882b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
58832fffb893SStefano Zampini     }
58842fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5885674ae819SStefano Zampini   }
58869b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
58879b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5888674ae819SStefano Zampini   }
5889674ae819SStefano Zampini 
5890674ae819SStefano Zampini   /* Setup of Graph */
58914b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
589214f95afaSStefano 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);
5893674ae819SStefano Zampini 
58944f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
58954f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
58964f1b2e48SStefano Zampini     PetscInt *local_subs;
58974f1b2e48SStefano Zampini 
58984f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
58994f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
59004f1b2e48SStefano Zampini       const PetscInt *idxs;
59014f1b2e48SStefano Zampini       PetscInt       nl,j;
59024f1b2e48SStefano Zampini 
59034f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
59044f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
590571582508SStefano Zampini       for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
59064f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
59074f1b2e48SStefano Zampini     }
59084f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
59094f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
59104f1b2e48SStefano Zampini   }
59114f1b2e48SStefano Zampini 
5912674ae819SStefano Zampini   /* Graph's connected components analysis */
5913674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
591471582508SStefano Zampini 
591571582508SStefano Zampini   /* set flag indicating analysis has been done */
591671582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_TRUE;
5917674ae819SStefano Zampini   PetscFunctionReturn(0);
5918674ae819SStefano Zampini }
5919674ae819SStefano Zampini 
59209a7d3425SStefano Zampini #undef __FUNCT__
59219a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
59229a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
59239a7d3425SStefano Zampini {
59249a7d3425SStefano Zampini   PetscInt       i,j;
59259a7d3425SStefano Zampini   PetscScalar    *alphas;
59269a7d3425SStefano Zampini   PetscErrorCode ierr;
59279a7d3425SStefano Zampini 
59289a7d3425SStefano Zampini   PetscFunctionBegin;
5929785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
59309a7d3425SStefano Zampini   for (i=0;i<n;i++) {
59319a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5932669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5933669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5934669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
59359a7d3425SStefano Zampini   }
59369a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
59379a7d3425SStefano Zampini   PetscFunctionReturn(0);
59389a7d3425SStefano Zampini }
59399a7d3425SStefano Zampini 
5940e7931f94SStefano Zampini #undef __FUNCT__
594170cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
594257de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5943e7931f94SStefano Zampini {
594457de7509SStefano Zampini   Mat            A;
5945e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5946e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
594752e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
594852e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
594927b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
595057de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
595127b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
595227b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
595327b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
595427b6a85dSStefano Zampini   MPI_Comm       subcomm;
595552e5ac9dSStefano Zampini   PetscErrorCode ierr;
5956a57a6d2fSStefano Zampini 
5957e7931f94SStefano Zampini   PetscFunctionBegin;
595857de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
595957de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
596057de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
596157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
596257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
596357de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
596457de7509SStefano Zampini 
596557de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
596657de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
596757de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
596857de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
596957de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
597057de7509SStefano Zampini   im_active = !!(n);
597157de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
597257de7509SStefano Zampini   void_procs = size - active_procs;
597357de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
597457de7509SStefano Zampini   if (void_procs) {
597557de7509SStefano Zampini     PetscInt ncand;
597657de7509SStefano Zampini 
597757de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
597857de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
597957de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
598057de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
598157de7509SStefano Zampini       if (!procs_candidates[i]) {
598257de7509SStefano Zampini         procs_candidates[ncand++] = i;
598357de7509SStefano Zampini       }
598457de7509SStefano Zampini     }
598557de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
598657de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
598757de7509SStefano Zampini   }
598857de7509SStefano Zampini 
598914f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
599014f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
599114f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
599214f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
599314f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
599414f0bfb9SStefano Zampini     else dest = rank;
599557de7509SStefano Zampini     if (im_active) {
599657de7509SStefano Zampini       issize = 1;
599757de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
599814f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
599957de7509SStefano Zampini       } else {
600014f0bfb9SStefano Zampini         isidx = dest;
600157de7509SStefano Zampini       }
600257de7509SStefano Zampini     } else {
600357de7509SStefano Zampini       issize = 0;
600457de7509SStefano Zampini       isidx = -1;
600557de7509SStefano Zampini     }
600657de7509SStefano Zampini     *n_subdomains = active_procs;
600757de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6008daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
600957de7509SStefano Zampini     PetscFunctionReturn(0);
601057de7509SStefano Zampini   }
6011c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6012c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
601327b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6014e7931f94SStefano Zampini 
6015e7931f94SStefano Zampini   /* Get info on mapping */
60163bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
60173bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6018e7931f94SStefano Zampini 
6019e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6020785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6021e7931f94SStefano Zampini   xadj[0] = 0;
6022e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6023785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6024785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
602527b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
602627b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
602727b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
602827b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6029e7931f94SStefano Zampini 
603027b6a85dSStefano Zampini   xadj_count = 0;
60312b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
603227b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
603327b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6034d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6035d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6036d023bfaeSStefano Zampini         xadj_count++;
603727b6a85dSStefano Zampini         break;
603827b6a85dSStefano Zampini       }
6039e7931f94SStefano Zampini     }
6040e7931f94SStefano Zampini   }
6041d023bfaeSStefano Zampini   xadj[1] = xadj_count;
604227b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
60433bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6044e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6045e7931f94SStefano Zampini 
60463837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6047e7931f94SStefano Zampini 
604827b6a85dSStefano Zampini   /* Restrict work on active processes only */
604927b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
605027b6a85dSStefano Zampini   if (void_procs) {
605127b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
605227b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
605327b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
605427b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
605527b6a85dSStefano Zampini   } else {
605627b6a85dSStefano Zampini     psubcomm = NULL;
605727b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
605827b6a85dSStefano Zampini   }
605927b6a85dSStefano Zampini 
606027b6a85dSStefano Zampini   v_wgt = NULL;
606127b6a85dSStefano Zampini   if (!color) {
6062e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6063e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6064e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6065c8587f34SStefano Zampini   } else {
606652e5ac9dSStefano Zampini     Mat             subdomain_adj;
606752e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
606852e5ac9dSStefano Zampini     MatPartitioning partitioner;
606927b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
607052e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
607157de7509SStefano Zampini     PetscMPIInt     size;
6072b0c7d250SStefano Zampini     PetscBool       aggregate;
6073b0c7d250SStefano Zampini 
607427b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
607527b6a85dSStefano Zampini     if (void_procs) {
607627b6a85dSStefano Zampini       PetscInt prank = rank;
6077785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
607827b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6079e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6080e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6081c8587f34SStefano Zampini       }
6082e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
608327b6a85dSStefano Zampini     } else {
608427b6a85dSStefano Zampini       oldranks = NULL;
608527b6a85dSStefano Zampini     }
6086b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
608727b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6088b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6089b0c7d250SStefano Zampini       PetscMPIInt nrank;
6090b0c7d250SStefano Zampini       PetscScalar *vals;
6091b0c7d250SStefano Zampini 
609227b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6093b0c7d250SStefano Zampini       lrows = 0;
6094b0c7d250SStefano Zampini       if (nrank<redprocs) {
6095b0c7d250SStefano Zampini         lrows = size/redprocs;
6096b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6097b0c7d250SStefano Zampini       }
609827b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6099b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6100b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6101b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6102b0c7d250SStefano Zampini       row = nrank;
6103b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6104b0c7d250SStefano Zampini       cols = adjncy;
6105b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6106b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6107b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6108b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6109b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
611052e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
611152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
611252e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6113b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
611427b6a85dSStefano Zampini       if (use_vwgt) {
611527b6a85dSStefano Zampini         Vec               v;
611627b6a85dSStefano Zampini         const PetscScalar *array;
611727b6a85dSStefano Zampini         PetscInt          nl;
611827b6a85dSStefano Zampini 
611927b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
612027b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
612127b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
612227b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
612327b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
612427b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
612527b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
612622db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
612727b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
612827b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
612927b6a85dSStefano Zampini       }
6130b0c7d250SStefano Zampini     } else {
613127b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
613227b6a85dSStefano Zampini       if (use_vwgt) {
613327b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
613427b6a85dSStefano Zampini         v_wgt[0] = local_size;
613527b6a85dSStefano Zampini       }
6136b0c7d250SStefano Zampini     }
613722b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6138e7931f94SStefano Zampini 
6139e7931f94SStefano Zampini     /* Partition */
614027b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6141e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
614227b6a85dSStefano Zampini     if (v_wgt) {
6143e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6144c8587f34SStefano Zampini     }
614557de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
614657de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6147e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6148e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
614922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6150e7931f94SStefano Zampini 
615152e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
61526583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
615352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
615452e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
615557de7509SStefano Zampini     if (!aggregate) {
615657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
615727b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
615827b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
615927b6a85dSStefano Zampini #endif
616057de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
616127b6a85dSStefano Zampini       } else if (oldranks) {
6162b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
616327b6a85dSStefano Zampini       } else {
616427b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
616557de7509SStefano Zampini       }
616628143c3dSStefano Zampini     } else {
6167b0c7d250SStefano Zampini       PetscInt    idxs[1];
6168b0c7d250SStefano Zampini       PetscMPIInt tag;
6169b0c7d250SStefano Zampini       MPI_Request *reqs;
6170b0c7d250SStefano Zampini 
6171b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6172b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6173b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
617427b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
617528143c3dSStefano Zampini       }
617627b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6177b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6178b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
617957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
618027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
618127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
618227b6a85dSStefano Zampini #endif
618357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
618427b6a85dSStefano Zampini       } else if (oldranks) {
6185b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
618627b6a85dSStefano Zampini       } else {
618727b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6188e7931f94SStefano Zampini       }
618957de7509SStefano Zampini     }
619052e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6191e7931f94SStefano Zampini     /* clean up */
6192e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
619352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6194e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6195e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6196e7931f94SStefano Zampini   }
619727b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
619857de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6199e7931f94SStefano Zampini 
6200e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6201e7931f94SStefano Zampini   i = 1;
620227b6a85dSStefano Zampini   if (!color) i=0;
620357de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6204e7931f94SStefano Zampini   PetscFunctionReturn(0);
6205e7931f94SStefano Zampini }
6206e7931f94SStefano Zampini 
6207e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6208e7931f94SStefano Zampini 
6209e7931f94SStefano Zampini #undef __FUNCT__
6210e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
62111ae86dd6SStefano 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[])
6212e7931f94SStefano Zampini {
621370cf5478SStefano Zampini   Mat                    local_mat;
6214e7931f94SStefano Zampini   IS                     is_sends_internal;
62159d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
62161ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
62179d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6218e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6219e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6220e7931f94SStefano Zampini   const PetscInt*        is_indices;
6221e7931f94SStefano Zampini   MatType                new_local_type;
6222e7931f94SStefano Zampini   /* buffers */
6223e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
622428143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
62259d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6226e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
62271ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6228e7931f94SStefano Zampini   /* MPI */
622928143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
623028143c3dSStefano Zampini   PetscSubcomm           subcomm;
6231e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
623228143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
623328143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
62341ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
62351ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
62361ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6237e7931f94SStefano Zampini   PetscErrorCode         ierr;
6238e7931f94SStefano Zampini 
6239e7931f94SStefano Zampini   PetscFunctionBegin;
624057de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6241e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
624228143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
624357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
624457de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
624557de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
624657de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
624757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
62481ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
62491ae86dd6SStefano Zampini   if (nvecs) {
62501ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
62511ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
62521ae86dd6SStefano Zampini   }
625357de7509SStefano Zampini   /* further checks */
6254e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6255e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6256e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6257e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6258e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
625957de7509SStefano Zampini   if (reuse && *mat_n) {
626070cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
626157de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
626270cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
626328143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
626470cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
626570cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
626670cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
626770cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
626870cf5478SStefano Zampini   }
6269e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6270e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
627157de7509SStefano Zampini 
6272e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6273e7931f94SStefano Zampini   if (!is_sends) {
627428143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
627557de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6276c8587f34SStefano Zampini   } else {
6277e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6278e7931f94SStefano Zampini     is_sends_internal = is_sends;
6279c8587f34SStefano Zampini   }
6280e7931f94SStefano Zampini 
6281e7931f94SStefano Zampini   /* get comm */
6282a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6283e7931f94SStefano Zampini 
6284e7931f94SStefano Zampini   /* compute number of sends */
6285e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6286e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6287e7931f94SStefano Zampini 
6288e7931f94SStefano Zampini   /* compute number of receives */
6289e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6290785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6291e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6292e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6293e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6294e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6295e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6296e7931f94SStefano Zampini 
629728143c3dSStefano Zampini   /* restrict comm if requested */
629828143c3dSStefano Zampini   subcomm = 0;
629928143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
630028143c3dSStefano Zampini   if (restrict_comm) {
6301779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6302779c1cceSStefano Zampini 
630328143c3dSStefano Zampini     color = 0;
630453a05cb3SStefano Zampini     if (restrict_full) {
630553a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
630653a05cb3SStefano Zampini     } else {
630753a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
630853a05cb3SStefano Zampini     }
6309b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
631028143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
631128143c3dSStefano Zampini     /* check if reuse has been requested */
631257de7509SStefano Zampini     if (reuse) {
631328143c3dSStefano Zampini       if (*mat_n) {
631428143c3dSStefano Zampini         PetscMPIInt subcommsize2;
631528143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
631628143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
631728143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
631828143c3dSStefano Zampini       } else {
631928143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
632028143c3dSStefano Zampini       }
632128143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6322779c1cceSStefano Zampini       PetscMPIInt rank;
6323779c1cceSStefano Zampini 
6324779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
632528143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
632628143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
632728143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6328306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
632928143c3dSStefano Zampini     }
633028143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
633128143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
633228143c3dSStefano Zampini   } else {
633328143c3dSStefano Zampini     comm_n = comm;
633428143c3dSStefano Zampini   }
633528143c3dSStefano Zampini 
6336e7931f94SStefano Zampini   /* prepare send/receive buffers */
6337785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6338e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6339785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6340e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
634128143c3dSStefano Zampini   if (nis) {
6342854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
634328143c3dSStefano Zampini   }
6344e7931f94SStefano Zampini 
634528143c3dSStefano Zampini   /* Get data from local matrices */
63466c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6347e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6348e7931f94SStefano Zampini     /*
6349e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6350e7931f94SStefano Zampini        send_buffer_idxs should contain:
6351e7931f94SStefano Zampini        - MatType_PRIVATE type
6352e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6353e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6354e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6355e7931f94SStefano Zampini     */
63566c4ed002SBarry Smith   else {
6357e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
63583bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6359854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6360e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6361e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
63623bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6363e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
63643bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6365e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6366e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6367e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6368e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6369c8587f34SStefano Zampini     }
6370c8587f34SStefano Zampini   }
6371e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
637228143c3dSStefano Zampini   /* additional is (if any) */
637328143c3dSStefano Zampini   if (nis) {
637428143c3dSStefano Zampini     PetscMPIInt psum;
637528143c3dSStefano Zampini     PetscInt j;
637628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
637728143c3dSStefano Zampini       PetscInt plen;
637828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
637928143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
638028143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
638128143c3dSStefano Zampini     }
6382854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
638328143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
638428143c3dSStefano Zampini       PetscInt plen;
638528143c3dSStefano Zampini       const PetscInt *is_array_idxs;
638628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
638728143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
638828143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
638928143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
639028143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
639128143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
639228143c3dSStefano Zampini     }
639328143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
639428143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
639528143c3dSStefano Zampini     }
639628143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
639728143c3dSStefano Zampini   }
639828143c3dSStefano Zampini 
6399e7931f94SStefano Zampini   buf_size_idxs = 0;
6400e7931f94SStefano Zampini   buf_size_vals = 0;
640128143c3dSStefano Zampini   buf_size_idxs_is = 0;
64021ae86dd6SStefano Zampini   buf_size_vecs = 0;
6403e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6404e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6405e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
640628143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
64071ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6408e7931f94SStefano Zampini   }
6409785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6410785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
641195ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
64121ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6413e7931f94SStefano Zampini 
6414e7931f94SStefano Zampini   /* get new tags for clean communications */
6415e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6416e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
641728143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
64181ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6419e7931f94SStefano Zampini 
6420e7931f94SStefano Zampini   /* allocate for requests */
6421785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6422785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
642395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
64241ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6425785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6426785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
642795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
64281ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6429e7931f94SStefano Zampini 
6430e7931f94SStefano Zampini   /* communications */
6431e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6432e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
643328143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
64341ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6435e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6436e7931f94SStefano Zampini     source_dest = onodes[i];
6437e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6438e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6439e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6440e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
644128143c3dSStefano Zampini     if (nis) {
644257de7509SStefano Zampini       source_dest = onodes_is[i];
644328143c3dSStefano 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);
644428143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
644528143c3dSStefano Zampini     }
64461ae86dd6SStefano Zampini     if (nvecs) {
64471ae86dd6SStefano Zampini       source_dest = onodes[i];
64481ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
64491ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
64501ae86dd6SStefano Zampini     }
6451e7931f94SStefano Zampini   }
6452e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6453e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6454e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6455e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
645628143c3dSStefano Zampini     if (nis) {
645728143c3dSStefano 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);
645828143c3dSStefano Zampini     }
64591ae86dd6SStefano Zampini     if (nvecs) {
64601ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64611ae86dd6SStefano 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);
64621ae86dd6SStefano Zampini     }
6463e7931f94SStefano Zampini   }
6464e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6465e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6466e7931f94SStefano Zampini 
6467e7931f94SStefano Zampini   /* assemble new l2g map */
6468e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6469e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64709d30be91SStefano Zampini   new_local_rows = 0;
6471e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64729d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6473e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6474e7931f94SStefano Zampini   }
64759d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);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     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
64809d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6481e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6482e7931f94SStefano Zampini   }
64839d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
64849d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6485e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6486e7931f94SStefano Zampini 
6487e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6488e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6489e7931f94SStefano 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) */
6490e7931f94SStefano Zampini   if (n_recvs) {
649128143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6492e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6493e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6494e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6495e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6496e7931f94SStefano Zampini         break;
6497e7931f94SStefano Zampini       }
6498e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6499e7931f94SStefano Zampini     }
6500e7931f94SStefano Zampini     switch (new_local_type_private) {
650128143c3dSStefano Zampini       case MATDENSE_PRIVATE:
650228143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6503e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6504e7931f94SStefano Zampini           bs = 1;
650528143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
650628143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
650728143c3dSStefano Zampini           bs = 1;
650828143c3dSStefano Zampini         }
6509e7931f94SStefano Zampini         break;
6510e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6511e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6512e7931f94SStefano Zampini         bs = 1;
6513e7931f94SStefano Zampini         break;
6514e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6515e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6516e7931f94SStefano Zampini         break;
6517e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6518e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6519e7931f94SStefano Zampini         break;
6520e7931f94SStefano Zampini       default:
65219d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6522e7931f94SStefano Zampini         break;
6523e7931f94SStefano Zampini     }
652428143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
652528143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
652628143c3dSStefano Zampini     bs = 1;
6527e7931f94SStefano Zampini   }
6528e7931f94SStefano Zampini 
652970cf5478SStefano Zampini   /* create MATIS object if needed */
653057de7509SStefano Zampini   if (!reuse) {
6531e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6532e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
653370cf5478SStefano Zampini   } else {
653470cf5478SStefano Zampini     /* it also destroys the local matrices */
653557de7509SStefano Zampini     if (*mat_n) {
653670cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
653757de7509SStefano Zampini     } else { /* this is a fake object */
653857de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
653957de7509SStefano Zampini     }
654070cf5478SStefano Zampini   }
654170cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6542e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
65439d30be91SStefano Zampini 
65449d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
65459d30be91SStefano Zampini 
65469d30be91SStefano Zampini   /* Global to local map of received indices */
65479d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
65489d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
65499d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
65509d30be91SStefano Zampini 
65519d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
65529d30be91SStefano Zampini   buf_size_idxs = 0;
65539d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
65549d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
65559d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
65569d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
65579d30be91SStefano Zampini   }
65589d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
65599d30be91SStefano Zampini 
65609d30be91SStefano Zampini   /* set preallocation */
65619d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
65629d30be91SStefano Zampini   if (!newisdense) {
65639d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
65649d30be91SStefano Zampini 
65659d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
65669d30be91SStefano Zampini     if (n_recvs) {
65679d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
65689d30be91SStefano Zampini     }
65699d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
65709d30be91SStefano Zampini       PetscInt j;
65719d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
65729d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
65739d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
65749d30be91SStefano Zampini         }
65759d30be91SStefano Zampini       } else {
65769d30be91SStefano Zampini         /* TODO */
65779d30be91SStefano Zampini       }
65789d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
65799d30be91SStefano Zampini     }
65809d30be91SStefano Zampini     if (new_local_nnz) {
65819d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
65829d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
65839d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
65849d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65859d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
65869d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65879d30be91SStefano Zampini     } else {
65889d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65899d30be91SStefano Zampini     }
65909d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
65919d30be91SStefano Zampini   } else {
65929d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65939d30be91SStefano Zampini   }
6594e7931f94SStefano Zampini 
6595e7931f94SStefano Zampini   /* set values */
6596e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
65979d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6598e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6599e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6600e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
66019d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6602e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6603e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6604e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
660528143c3dSStefano Zampini     } else {
660628143c3dSStefano Zampini       /* TODO */
6607e7931f94SStefano Zampini     }
6608e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6609e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6610e7931f94SStefano Zampini   }
6611e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6612e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
661370cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
661470cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66159d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6616e7931f94SStefano Zampini 
6617dfd14d43SStefano Zampini #if 0
661828143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6619e7931f94SStefano Zampini     Vec       lvec,rvec;
6620e7931f94SStefano Zampini     PetscReal infty_error;
6621e7931f94SStefano Zampini 
66222a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6623e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6624e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6625e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
662670cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6627e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6628e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6629e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6630e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6631e7931f94SStefano Zampini   }
663228143c3dSStefano Zampini #endif
6633e7931f94SStefano Zampini 
663428143c3dSStefano Zampini   /* assemble new additional is (if any) */
663528143c3dSStefano Zampini   if (nis) {
663628143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
663728143c3dSStefano Zampini 
663828143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6639854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
664028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
664128143c3dSStefano Zampini     psum = 0;
664228143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
664328143c3dSStefano Zampini       for (j=0;j<nis;j++) {
664428143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
664528143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
664628143c3dSStefano Zampini         psum += plen;
664728143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
664828143c3dSStefano Zampini       }
664928143c3dSStefano Zampini     }
6650854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6651854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
665228143c3dSStefano Zampini     for (i=1;i<nis;i++) {
665328143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
665428143c3dSStefano Zampini     }
665528143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
665628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
665728143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
665828143c3dSStefano Zampini       for (j=0;j<nis;j++) {
665928143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
666028143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
666128143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
666228143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
666328143c3dSStefano Zampini       }
666428143c3dSStefano Zampini     }
666528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
666628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
666728143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
666828143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
666928143c3dSStefano Zampini     }
667028143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
667128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
667228143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
667328143c3dSStefano Zampini   }
6674e7931f94SStefano Zampini   /* free workspace */
667528143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6676e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6677e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6678e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6679e7931f94SStefano Zampini   if (isdense) {
6680e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6681e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6682e7931f94SStefano Zampini   } else {
6683e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6684e7931f94SStefano Zampini   }
668528143c3dSStefano Zampini   if (nis) {
668628143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
668728143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
668828143c3dSStefano Zampini   }
66891ae86dd6SStefano Zampini 
66901ae86dd6SStefano Zampini   if (nvecs) {
66911ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66921ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66931ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
66941ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
66951ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
66961ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
66971ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
66981ae86dd6SStefano Zampini     /* set values */
66991ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
67001ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
67011ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67021ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
67031ae86dd6SStefano Zampini       PetscInt j;
67041ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
67051ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
67061ae86dd6SStefano Zampini       }
67071ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
67081ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
67091ae86dd6SStefano Zampini     }
67101ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67111ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
67121ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
67131ae86dd6SStefano Zampini   }
67141ae86dd6SStefano Zampini 
67151ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
67161ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6717e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6718e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
67191ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
672028143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6721e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6722e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
67231ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
672428143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6725e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6726e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6727e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6728e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6729e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
673028143c3dSStefano Zampini   if (nis) {
673128143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
673228143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
673328143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
673428143c3dSStefano Zampini   }
673528143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
673628143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
673728143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
673828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
673928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
674028143c3dSStefano Zampini     }
67411ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
67421ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
67431ae86dd6SStefano Zampini     }
674453a05cb3SStefano Zampini     *mat_n = NULL;
674528143c3dSStefano Zampini   }
6746e7931f94SStefano Zampini   PetscFunctionReturn(0);
6747e7931f94SStefano Zampini }
6748a57a6d2fSStefano Zampini 
674912edc857SStefano Zampini /* temporary hack into ksp private data structure */
6750af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
675112edc857SStefano Zampini 
6752c8587f34SStefano Zampini #undef __FUNCT__
6753c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6754c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6755c8587f34SStefano Zampini {
6756c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6757c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
675820a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
67591ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
67609881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
676120a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
67626e683305SStefano Zampini   IS                     coarse_is,*isarray;
67636e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
676430368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6765f9eb5b7dSStefano Zampini   PC                     pc_temp;
6766c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6767c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6768f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
67694f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
67706e683305SStefano Zampini   Mat                    t_coarse_mat_is;
677157de7509SStefano Zampini   PetscInt               ncoarse;
677268457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
677322bc73bbSStefano Zampini   PetscScalar            *array;
677457de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
677557de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
67769881197aSStefano Zampini   PetscErrorCode         ierr;
6777fdc09c96SStefano Zampini 
6778c8587f34SStefano Zampini   PetscFunctionBegin;
6779c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
678068457ee5SStefano 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 */
6781fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
67825a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6783fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6784f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6785f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6786f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6787fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
678851bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
678951bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6790dc4bcba2SStefano Zampini         PC        pc;
6791dc4bcba2SStefano Zampini         PetscBool isbddc;
6792dc4bcba2SStefano Zampini 
6793dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6794dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6795dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6796dc4bcba2SStefano Zampini         if (isbddc) {
679763c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
679863c961adSStefano Zampini         } else {
6799727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
680063c961adSStefano Zampini         }
6801fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6802fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6803fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6804f4ddd8eeSStefano Zampini       }
6805fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6806fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6807f4ddd8eeSStefano Zampini     }
680870cf5478SStefano Zampini     /* reset any subassembling information */
680957de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
681070cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
681157de7509SStefano Zampini     }
68126e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6813fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6814f4ddd8eeSStefano Zampini   }
681557de7509SStefano Zampini   /* assemble coarse matrix */
681657de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
681757de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
681857de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
681957de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
682018a45a71SStefano Zampini   } else {
682157de7509SStefano Zampini     coarse_mat = NULL;
682257de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
68236e683305SStefano Zampini   }
6824e7931f94SStefano Zampini 
6825abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6826abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6827abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6828abbbba34SStefano Zampini 
6829abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
683022bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
683122bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
683222bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
683322bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6834e176bc59SStefano 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);
68356e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
68366e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68376e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6838abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6839abbbba34SStefano Zampini 
684057de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
684157de7509SStefano Zampini   im_active = !!(pcis->n);
684257de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
684357de7509SStefano Zampini 
684414f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
684557de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
684657de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
684757de7509SStefano Zampini   coarse_mat_is = NULL;
684857de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
684957de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
685057de7509SStefano Zampini   full_restr = PETSC_TRUE;
68511ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
685257de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
685357de7509SStefano Zampini   if (multilevel_requested) {
685457de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
685557de7509SStefano Zampini     restr = PETSC_FALSE;
685657de7509SStefano Zampini     full_restr = PETSC_FALSE;
685757de7509SStefano Zampini   } else {
685857de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
685957de7509SStefano Zampini     restr = PETSC_TRUE;
686057de7509SStefano Zampini     full_restr = PETSC_TRUE;
686157de7509SStefano Zampini   }
68624b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
686357de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
686457de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6865a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
686657de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6867a198735bSStefano Zampini     } else {
6868a198735bSStefano Zampini       PetscMPIInt size,rank;
6869a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6870a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6871a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6872a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6873a198735bSStefano Zampini     }
687457de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
687557de7509SStefano Zampini     PetscInt    psum;
687657de7509SStefano Zampini     PetscMPIInt size;
687757de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
687857de7509SStefano Zampini     else psum = 0;
687957de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
688057de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
688157de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
688257de7509SStefano Zampini   }
688357de7509SStefano Zampini   /* determine if we can go multilevel */
688457de7509SStefano Zampini   if (multilevel_requested) {
688557de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
688657de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
688757de7509SStefano Zampini   }
688857de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
688957de7509SStefano Zampini 
6890e4d548c7SStefano Zampini   /* dump subassembling pattern */
6891e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6892e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6893e4d548c7SStefano Zampini   }
6894e4d548c7SStefano Zampini 
68956e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
6896*c703fcc7SStefano Zampini   if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
68976e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
68986e683305SStefano Zampini     const PetscInt         *idxs;
68996e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
69006e683305SStefano Zampini 
69016e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
69020be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
69036e683305SStefano Zampini     /* allocate space for temporary storage */
6904854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6905854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
69066e683305SStefano Zampini     /* allocate for IS array */
69076e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
69086e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
690927b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
691030368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6911854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
69126e683305SStefano Zampini     /* dofs splitting */
69136e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
69146e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
69156e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
69166e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69176e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69186e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69196e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
692030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
69216e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
69226e683305SStefano Zampini     }
69236e683305SStefano Zampini     /* neumann boundaries */
69246e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
69256e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
69266e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
69276e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69286e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69296e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69306e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
693130368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
69326e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
69336e683305SStefano Zampini     }
69346e683305SStefano Zampini     /* free memory */
69356e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
69366e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
69376e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
69386e683305SStefano Zampini   } else {
69396e683305SStefano Zampini     nis = 0;
69406e683305SStefano Zampini     nisdofs = 0;
69416e683305SStefano Zampini     nisneu = 0;
694230368db7SStefano Zampini     nisvert = 0;
69436e683305SStefano Zampini     isarray = NULL;
69446e683305SStefano Zampini   }
69456e683305SStefano Zampini   /* destroy no longer needed map */
69466e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
69476e683305SStefano Zampini 
694857de7509SStefano Zampini   /* subassemble */
694957de7509SStefano Zampini   if (multilevel_allowed) {
69501ae86dd6SStefano Zampini     Vec       vp[1];
69511ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
695257de7509SStefano Zampini     PetscBool reuse,reuser;
69531ae86dd6SStefano Zampini 
695457de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
695557de7509SStefano Zampini     else reuse = PETSC_FALSE;
695657de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
69571ae86dd6SStefano Zampini     vp[0] = NULL;
69581ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
69591ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
69601ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
69611ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
69621ae86dd6SStefano Zampini       nvecs = 1;
69631ae86dd6SStefano Zampini 
69641ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6965a198735bSStefano Zampini         Mat      B,loc_divudotp;
69661ae86dd6SStefano Zampini         Vec      v,p;
69671ae86dd6SStefano Zampini         IS       dummy;
69681ae86dd6SStefano Zampini         PetscInt np;
69691ae86dd6SStefano Zampini 
6970a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6971a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
69721ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6973a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
69741ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
69751ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
69761ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
69771ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
69781ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
69791ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
69801ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
69811ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
69821ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
69831ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
69841ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
69851ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
698674e2c79eSStefano Zampini       }
69871ae86dd6SStefano Zampini     }
69881ae86dd6SStefano Zampini     if (reuser) {
69891ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
699074e2c79eSStefano Zampini     } else {
69911ae86dd6SStefano 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);
69921ae86dd6SStefano Zampini     }
69931ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
69941ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
69951ae86dd6SStefano Zampini       PetscInt    nl;
69961ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
69971ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
69981ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
69991ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
70001ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
70011ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
70021ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
70031ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7004a198735bSStefano Zampini     } else {
7005a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
70061ae86dd6SStefano Zampini     }
70071ae86dd6SStefano Zampini   } else {
70081ae86dd6SStefano 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);
70096e683305SStefano Zampini   }
701057de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
701157de7509SStefano Zampini     PetscMPIInt size;
701257de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
701357de7509SStefano Zampini     if (!multilevel_allowed) {
701457de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
70156e683305SStefano Zampini     } else {
701657de7509SStefano Zampini       Mat A;
7017779c1cceSStefano Zampini 
701857de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
701957de7509SStefano Zampini       if (coarse_mat_is) {
702057de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
702157de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
702257de7509SStefano Zampini         coarse_mat = coarse_mat_is;
702357de7509SStefano Zampini       }
702457de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
702557de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
702657de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7027779c1cceSStefano Zampini     }
7028779c1cceSStefano Zampini   }
702957de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
703057de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
70316e683305SStefano Zampini 
70326e683305SStefano Zampini   /* create local to global scatters for coarse problem */
703368457ee5SStefano Zampini   if (compute_vecs) {
70346e683305SStefano Zampini     PetscInt lrows;
70356e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
703657de7509SStefano Zampini     if (coarse_mat) {
703757de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
70386e683305SStefano Zampini     } else {
70396e683305SStefano Zampini       lrows = 0;
70406e683305SStefano Zampini     }
70416e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
70426e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
70436e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
70446e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70456e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70466e683305SStefano Zampini   }
70476e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7048c8587f34SStefano Zampini 
7049f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7050f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7051f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7052f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7053f9eb5b7dSStefano Zampini   } else {
7054f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7055f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7056c8587f34SStefano Zampini   }
7057c8587f34SStefano Zampini 
70586e683305SStefano Zampini   /* print some info if requested */
70596e683305SStefano Zampini   if (pcbddc->dbg_flag) {
70606e683305SStefano Zampini     if (!multilevel_allowed) {
70616e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
70626e683305SStefano Zampini       if (multilevel_requested) {
70636e683305SStefano 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);
70646e683305SStefano Zampini       } else if (pcbddc->max_levels) {
70656e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
70666e683305SStefano Zampini       }
70676e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
70686e683305SStefano Zampini     }
70696e683305SStefano Zampini   }
70706e683305SStefano Zampini 
7071f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
707257de7509SStefano Zampini   if (coarse_mat) {
70736a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
70746e683305SStefano Zampini     if (pcbddc->dbg_flag) {
707557de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
70766e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
70776e683305SStefano Zampini     }
7078f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7079312be037SStefano Zampini       char prefix[256],str_level[16];
7080e604994aSStefano Zampini       size_t len;
708157de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7082422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7083c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7084f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
708557de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7086c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
70876e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7088c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
7089c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7090e604994aSStefano Zampini       /* prefix */
7091e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7092e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7093e604994aSStefano Zampini       if (!pcbddc->current_level) {
7094e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7095e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7096c8587f34SStefano Zampini       } else {
7097e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7098312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7099312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
710034d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7101312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7102e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7103e604994aSStefano Zampini       }
7104e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
71053e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
71063e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
71073e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
71083e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7109f9eb5b7dSStefano Zampini       /* allow user customization */
7110f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
71113e3c6dadSStefano Zampini     }
71123e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
711351bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
71143e3c6dadSStefano Zampini     if (nisdofs) {
71153e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
71163e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
71173e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
71183e3c6dadSStefano Zampini       }
71193e3c6dadSStefano Zampini     }
71203e3c6dadSStefano Zampini     if (nisneu) {
71213e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
71223e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7123312be037SStefano Zampini     }
712430368db7SStefano Zampini     if (nisvert) {
712530368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
712630368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
712730368db7SStefano Zampini     }
7128f9eb5b7dSStefano Zampini 
7129f9eb5b7dSStefano Zampini     /* get some info after set from options */
7130f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7131f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
71324f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
71336e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7134f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7135f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7136f9eb5b7dSStefano Zampini     }
713739f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
71384f3a063dSStefano Zampini     if (isredundant) {
71394f3a063dSStefano Zampini       KSP inner_ksp;
71404f3a063dSStefano Zampini       PC  inner_pc;
71414f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
71424f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
71434f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
71444f3a063dSStefano Zampini     }
7145f9eb5b7dSStefano Zampini 
714657de7509SStefano Zampini     /* parameters which miss an API */
714757de7509SStefano Zampini     if (isbddc) {
7148720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7149720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
715057de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
715127b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
715227b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7153a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7154a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7155a198735bSStefano Zampini         IS                     row,col;
7156a198735bSStefano Zampini         const PetscInt         *gidxs;
7157a198735bSStefano Zampini         PetscInt               n,st,M,N;
7158a198735bSStefano Zampini 
7159a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7160a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7161a198735bSStefano Zampini         st = st-n;
7162a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7163a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7164a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7165a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7166a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7167a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7168a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7169a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7170a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7171a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7172a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7173a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7174a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7175a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7176a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7177a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7178a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7179a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7180a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7181a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
71828ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7183a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7184720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
718559e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7186720d30f9SStefano Zampini       }
7187d4d8cf7bSStefano Zampini     }
71889881197aSStefano Zampini 
71893301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
71905a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
71913301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
71923301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
71933301b35fSStefano Zampini     }
71943301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
71953301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
71963301b35fSStefano Zampini     }
71973301b35fSStefano Zampini     if (pc->pmat->spd_set) {
71983301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
71993301b35fSStefano Zampini     }
720027b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
720127b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
720227b6a85dSStefano Zampini     }
72036e683305SStefano Zampini     /* set operators */
72045f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
72056e683305SStefano Zampini     if (pcbddc->dbg_flag) {
72066e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
72076e683305SStefano Zampini     }
72086e683305SStefano Zampini   }
72096e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7210b1ecc7b1SStefano Zampini #if 0
7211b9b85e73SStefano Zampini   {
7212b9b85e73SStefano Zampini     PetscViewer viewer;
7213b9b85e73SStefano Zampini     char filename[256];
7214b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7215b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
72166a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7217b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7218f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7219b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7220b9b85e73SStefano Zampini   }
7221b9b85e73SStefano Zampini #endif
7222f9eb5b7dSStefano Zampini 
722398a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
722498a51de6SStefano Zampini     Vec crhs,csol;
722504708bb6SStefano Zampini 
7226f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7227f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7228f347579bSStefano Zampini     if (!csol) {
72292a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7230f9eb5b7dSStefano Zampini     }
7231f347579bSStefano Zampini     if (!crhs) {
72322a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7233f347579bSStefano Zampini     }
7234b0f5fe93SStefano Zampini   }
72351ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7236b0f5fe93SStefano Zampini 
7237b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7238b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7239b0f5fe93SStefano Zampini 
7240b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
72414f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
72424f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
72434f1b2e48SStefano Zampini     }
7244b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7245b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7246b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7247b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7248b0f5fe93SStefano Zampini     if (coarse_mat) {
7249b0f5fe93SStefano Zampini       Vec         nullv;
7250b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7251b0f5fe93SStefano Zampini       PetscInt    nl;
7252b0f5fe93SStefano Zampini 
7253b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7254b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7255b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7256b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7257b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7258b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7259b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7260b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7261b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7262b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7263b0f5fe93SStefano Zampini     }
7264b0f5fe93SStefano Zampini   }
7265b0f5fe93SStefano Zampini 
7266b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7267b0f5fe93SStefano Zampini     PetscBool ispreonly;
7268b0f5fe93SStefano Zampini 
7269b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7270b0f5fe93SStefano Zampini       PetscBool isnull;
7271b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7272bef83e63SStefano Zampini       if (isnull) {
7273b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7274b0f5fe93SStefano Zampini       }
7275bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7276b0f5fe93SStefano Zampini     }
7277b0f5fe93SStefano Zampini     /* setup coarse ksp */
7278b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7279cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7280cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
72816e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7282c8587f34SStefano Zampini       KSP       check_ksp;
72832b510759SStefano Zampini       KSPType   check_ksp_type;
7284c8587f34SStefano Zampini       PC        check_pc;
72856e683305SStefano Zampini       Vec       check_vec,coarse_vec;
72866a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
72872b510759SStefano Zampini       PetscInt  its;
72886e683305SStefano Zampini       PetscBool compute_eigs;
72896e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
72906e683305SStefano Zampini       PetscInt  neigs;
72918e185a42SStefano Zampini       const char *prefix;
7292c8587f34SStefano Zampini 
72932b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
72946e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7295422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
729623ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7297f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7298e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7299e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7300e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
73012b510759SStefano Zampini       if (ispreonly) {
73022b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
73036e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
73042b510759SStefano Zampini       } else {
7305cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
73066e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7307c8587f34SStefano Zampini       }
7308c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
73096e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
73106e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
73116e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7312a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7313a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7314a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7315a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7316c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7317c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7318c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7319c8587f34SStefano Zampini       /* create random vec */
73202701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7321c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
73226e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7323c8587f34SStefano Zampini       /* solve coarse problem */
73246e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7325cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
73266e683305SStefano Zampini       if (compute_eigs) {
7327854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7328854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
73296e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
73301ae86dd6SStefano Zampini         if (neigs) {
73316e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
73326e683305SStefano Zampini           lambda_min = eigs_r[0];
73336e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
73342701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
73352701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7336cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7337cbcc2c2aSStefano Zampini             }
7338c8587f34SStefano Zampini           }
7339c8587f34SStefano Zampini         }
73401ae86dd6SStefano Zampini       }
7341cbcc2c2aSStefano Zampini 
7342c8587f34SStefano Zampini       /* check coarse problem residual error */
73436e683305SStefano Zampini       if (pcbddc->dbg_flag) {
73446e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
73456e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73466e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7347c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
73486e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
73496e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7350779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
73516e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
73526e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
73536e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
73546e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7355b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7356b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7357b0f5fe93SStefano Zampini         }
73586e683305SStefano Zampini         if (compute_eigs) {
73596e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7360deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7361c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
73626e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
73636e683305SStefano 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);
73646e683305SStefano Zampini           for (i=0;i<neigs;i++) {
73656e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7366c8587f34SStefano Zampini           }
73676e683305SStefano Zampini         }
73686e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
73696e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73706e683305SStefano Zampini       }
7371e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
73722701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7373c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
73746e683305SStefano Zampini       if (compute_eigs) {
73756e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
73766e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7377c8587f34SStefano Zampini       }
73786e683305SStefano Zampini     }
73796e683305SStefano Zampini   }
7380bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7381cbcc2c2aSStefano Zampini   /* print additional info */
7382cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
73836e683305SStefano Zampini     /* waits until all processes reaches this point */
73846e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7385cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7386cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7387cbcc2c2aSStefano Zampini   }
7388cbcc2c2aSStefano Zampini 
73892b510759SStefano Zampini   /* free memory */
7390fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7391c8587f34SStefano Zampini   PetscFunctionReturn(0);
7392c8587f34SStefano Zampini }
7393674ae819SStefano Zampini 
7394f34684f1SStefano Zampini #undef __FUNCT__
7395f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7396f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7397f34684f1SStefano Zampini {
7398f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7399f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7400f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7401dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7402dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
740373be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7404dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7405f34684f1SStefano Zampini   PetscErrorCode ierr;
7406f34684f1SStefano Zampini 
7407f34684f1SStefano Zampini   PetscFunctionBegin;
7408f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
74096c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7410dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
74113bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7412dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7413dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
74146583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7415dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7416dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7417dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
74186c4ed002SBarry 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);
7419dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7420dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7421dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7422dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7423dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7424f34684f1SStefano Zampini 
7425f34684f1SStefano Zampini   /* check numbering */
7426f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7427019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7428dc456d91SStefano Zampini     PetscInt    i;
7429b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7430f34684f1SStefano Zampini 
7431f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7432f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7433f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
74341575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7435019a44ceSStefano Zampini     /* counter */
7436019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7437019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7438019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7439019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7440019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7441019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7442f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7443f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7444727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7445f34684f1SStefano Zampini     }
7446f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7447f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7448f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7449e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7450e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7451e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7452e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7453f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7454019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7455f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7456019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
74572c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
745875c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7459b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
74602c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
74612c66d082SStefano 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);
7462f34684f1SStefano Zampini       }
7463f34684f1SStefano Zampini     }
7464019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7465b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7466f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7467f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7468f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7469f34684f1SStefano Zampini     }
7470f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7471f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7472e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7473e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7474f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7475f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7476b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7477ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7478ca8b9ea9SStefano Zampini 
7479ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
74803bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7481f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7482f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7483f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7484f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
74854bc2dc4bSStefano 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);
7486f34684f1SStefano Zampini       }
7487f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7488ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7489f34684f1SStefano Zampini     }
7490f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74911575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7492302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7493f34684f1SStefano Zampini   }
74948bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7495f34684f1SStefano Zampini   /* get back data */
7496f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7497f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7498674ae819SStefano Zampini   PetscFunctionReturn(0);
7499674ae819SStefano Zampini }
7500674ae819SStefano Zampini 
7501e456f2a8SStefano Zampini #undef __FUNCT__
7502e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7503a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7504e456f2a8SStefano Zampini {
7505e456f2a8SStefano Zampini   IS             localis_t;
7506a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7507e456f2a8SStefano Zampini   PetscScalar    *vals;
7508e456f2a8SStefano Zampini   PetscErrorCode ierr;
7509e456f2a8SStefano Zampini 
7510e456f2a8SStefano Zampini   PetscFunctionBegin;
7511a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7512e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7513854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7514e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7515e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7516a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7517a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
75181035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7519a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
75201035eff8SStefano Zampini   }
7521a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7522e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7523e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7524a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7525a7dc3881SStefano Zampini   /* now compute set in local ordering */
7526a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7527a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7528a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7529a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7530a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7531ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7532e456f2a8SStefano Zampini       lsize++;
7533e456f2a8SStefano Zampini     }
7534e456f2a8SStefano Zampini   }
7535854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7536a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7537ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7538e456f2a8SStefano Zampini       idxs[lsize++] = i;
7539e456f2a8SStefano Zampini     }
7540e456f2a8SStefano Zampini   }
7541a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7542a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7543e456f2a8SStefano Zampini   *localis = localis_t;
7544e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7545e456f2a8SStefano Zampini }
7546906d46d4SStefano Zampini 
7547b96c3477SStefano Zampini #undef __FUNCT__
7548b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
754908122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7550b96c3477SStefano Zampini {
7551a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7552b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7553b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7554a64f4aa4SStefano Zampini   Mat                 S_j;
7555b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7556b96c3477SStefano Zampini   PetscBool           free_used_adj;
7557b96c3477SStefano Zampini   PetscErrorCode      ierr;
7558b96c3477SStefano Zampini 
7559b96c3477SStefano Zampini   PetscFunctionBegin;
7560b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7561b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
756208122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7563b96c3477SStefano Zampini     used_xadj = NULL;
7564b96c3477SStefano Zampini     used_adjncy = NULL;
7565b96c3477SStefano Zampini   } else {
756608122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
756708122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
756808122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
756908122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7570b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7571b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7572b96c3477SStefano Zampini     } else {
75732fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7574b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7575b96c3477SStefano Zampini       PetscInt       nvtxs;
7576b96c3477SStefano Zampini 
75772fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
75782fffb893SStefano Zampini       if (flg_row) {
7579b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7580b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7581b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7582b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
75832fffb893SStefano Zampini       } else {
75842fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
75852fffb893SStefano Zampini         used_xadj = NULL;
75862fffb893SStefano Zampini         used_adjncy = NULL;
75872fffb893SStefano Zampini       }
75882fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7589b96c3477SStefano Zampini     }
7590b96c3477SStefano Zampini   }
7591d5574798SStefano Zampini 
7592d5574798SStefano Zampini   /* setup sub_schurs data */
7593a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7594df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7595df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7596a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
759791af6908SStefano 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);
7598a64f4aa4SStefano Zampini   } else {
75996816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
76004d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7601a3df083aSStefano Zampini     PetscInt  benign_n;
760272b8c272SStefano Zampini     Mat       change = NULL;
76039d54b7f4SStefano Zampini     Vec       scaling = NULL;
760472b8c272SStefano Zampini     IS        change_primal = NULL;
7605a3df083aSStefano Zampini 
76065feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
76075feab87aSStefano Zampini       PetscInt n_vertices;
76085feab87aSStefano Zampini 
76095feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
76102034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
76115feab87aSStefano Zampini     }
761204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
761304708bb6SStefano Zampini     if (!isseqaij) {
761404708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
761504708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
761604708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
761704708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
761804708bb6SStefano Zampini       } else {
7619511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
762004708bb6SStefano Zampini       }
762104708bb6SStefano Zampini     }
7622a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7623a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7624ca92afb2SStefano Zampini     } else {
7625a3df083aSStefano Zampini       benign_n = 0;
7626ca92afb2SStefano Zampini     }
7627b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7628b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7629b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
763072b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
763122db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7632b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
763322db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7634b7ab4a40SStefano Zampini     }
7635b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7636b7ab4a40SStefano 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 */
7637b7ab4a40SStefano Zampini     if (need_change) {
763888c03ad3SStefano Zampini       PC_IS   *pcisf;
763988c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
764088c03ad3SStefano Zampini       PC      pcf;
764188c03ad3SStefano Zampini 
7642e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
764388c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
764488c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
764588c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
764688c03ad3SStefano Zampini       /* hacks */
764788c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
764872b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
764972b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
765072b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
765172b8c272SStefano Zampini       pcisf->n = pcis->n;
765272b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
765388c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
765488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
765588c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
765688c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
765788c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
765888c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
765972b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
766088c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
766188c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
766272b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
766372b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
766472b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
766572b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
766672b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
766788c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
766872b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
766988c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
767088c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
767188c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
767288c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
767388c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
767488c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
767588c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
767688c03ad3SStefano Zampini     }
76779d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
767891af6908SStefano 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);
767972b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
768072b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7681ca92afb2SStefano Zampini   }
7682d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7683b96c3477SStefano Zampini 
7684b96c3477SStefano Zampini   /* free adjacency */
7685b96c3477SStefano Zampini   if (free_used_adj) {
7686b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7687b96c3477SStefano Zampini   }
7688b96c3477SStefano Zampini   PetscFunctionReturn(0);
7689b96c3477SStefano Zampini }
7690b96c3477SStefano Zampini 
7691b96c3477SStefano Zampini #undef __FUNCT__
7692b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
769308122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7694b96c3477SStefano Zampini {
7695b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7696b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7697b96c3477SStefano Zampini   PCBDDCGraph         graph;
7698b96c3477SStefano Zampini   PetscErrorCode      ierr;
7699b96c3477SStefano Zampini 
7700b96c3477SStefano Zampini   PetscFunctionBegin;
7701b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
770208122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
77033301b35fSStefano Zampini     IS       verticesIS,verticescomm;
77043301b35fSStefano Zampini     PetscInt vsize,*idxs;
7705b96c3477SStefano Zampini 
7706b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
77073301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
77083301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
77093301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
77103301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7711c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7712b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7713be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7714441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
77153301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7716b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7717b96c3477SStefano Zampini   } else {
7718b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7719b96c3477SStefano Zampini   }
7720e4d548c7SStefano Zampini   /* print some info */
7721e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7722e4d548c7SStefano Zampini     IS       vertices;
7723e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7724c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7725e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7726e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7727e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7728e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7729e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7730e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7731e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7732e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7733e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7734c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7735e4d548c7SStefano Zampini   }
7736b96c3477SStefano Zampini 
7737b96c3477SStefano Zampini   /* sub_schurs init */
7738b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7739b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7740b334f244SStefano Zampini   }
7741b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7742a64f4aa4SStefano Zampini 
7743b96c3477SStefano Zampini   /* free graph struct */
774408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7745b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7746b96c3477SStefano Zampini   }
7747b96c3477SStefano Zampini   PetscFunctionReturn(0);
7748b96c3477SStefano Zampini }
7749fa34dd3eSStefano Zampini 
7750fa34dd3eSStefano Zampini #undef __FUNCT__
7751fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7752fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7753fa34dd3eSStefano Zampini {
7754fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7755fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7756fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7757fa34dd3eSStefano Zampini 
7758fa34dd3eSStefano Zampini   PetscFunctionBegin;
7759fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7760fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
77614f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7762fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
77634f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
776475c01103SStefano Zampini     PetscReal      norm;
7765fa34dd3eSStefano Zampini     PetscInt       i;
7766fa34dd3eSStefano Zampini 
7767fa34dd3eSStefano Zampini     /* B0 and B0_B */
7768fa34dd3eSStefano Zampini     if (zerodiag) {
7769fa34dd3eSStefano Zampini       IS       dummy;
7770fa34dd3eSStefano Zampini 
77714f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
77724f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7773fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7774fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7775fa34dd3eSStefano Zampini     }
7776fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7777fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7778fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7779fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7780fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7781fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7782fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7783fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7784fa34dd3eSStefano Zampini     /* S_j */
7785fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7786fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7787fa34dd3eSStefano Zampini 
7788fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7789fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7790fa34dd3eSStefano Zampini     /* continuous in primal space */
7791fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7792fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7793fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7794fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
77954f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
77964f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7797fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7798fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7799fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7800fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7801fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7802fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7803fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7804fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7805fa34dd3eSStefano Zampini 
7806fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7807fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7808fa34dd3eSStefano Zampini     /* local with Schur */
7809fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7810fa34dd3eSStefano Zampini     if (zerodiag) {
7811fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78124f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7813fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7814fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7815fa34dd3eSStefano Zampini     }
7816fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7817fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7818fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7819fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7820fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7821fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7822fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7823fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7824fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7825fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7826fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7827fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7828fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7829fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7830fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7831fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7832fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7833fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7834fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7835fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7836fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7837fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7838fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7839fa34dd3eSStefano Zampini     if (zerodiag) {
7840fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7841fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78424f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7843fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7844fa34dd3eSStefano Zampini     }
7845fa34dd3eSStefano Zampini     /* BDDC */
7846fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7847fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7848fa34dd3eSStefano Zampini 
7849fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7850fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7851fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7852fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
78534f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
78544f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7855fa34dd3eSStefano Zampini     }
78564f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7857fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7858fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7859fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7860fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7861fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7862fa34dd3eSStefano Zampini   }
7863fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7864fa34dd3eSStefano Zampini }
7865