xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 62b0c6f7b53b95e36b0448aa9f9898924076a299)
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);
314*62b0c6f7SStefano Zampini   ierr = PetscBTCreate(ne,&btee);CHKERRQ(ierr);
315a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
316*62b0c6f7SStefano Zampini   for (i=1;i<n_neigh;i++)
317*62b0c6f7SStefano Zampini     for (j=0;j<n_shared[i];j++)
318*62b0c6f7SStefano Zampini       marks[shared[i][j]]++;
319a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
320*62b0c6f7SStefano Zampini   for (i=0;i<ne;i++) {
321*62b0c6f7SStefano Zampini     if (marks[i] > 1 || (marks[i] == 1 && PetscBTLookup(btb,i))) {
322*62b0c6f7SStefano Zampini       ierr = PetscBTSet(btee,i);CHKERRQ(ierr);
323*62b0c6f7SStefano Zampini     }
324*62b0c6f7SStefano Zampini   }
325*62b0c6f7SStefano Zampini 
326*62b0c6f7SStefano Zampini   if (!conforming) {
327*62b0c6f7SStefano Zampini     ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
328*62b0c6f7SStefano Zampini     ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
329*62b0c6f7SStefano 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);
332*62b0c6f7SStefano Zampini   cum  = 0;
333a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
334dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
335*62b0c6f7SStefano Zampini     if (!PetscBTLookup(btee,i)) {
336a13144ffSStefano Zampini       marks[cum++] = i;
337dec27d64SStefano Zampini       continue;
338dec27d64SStefano Zampini     }
339dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
340*62b0c6f7SStefano Zampini     if (!conforming) {
341*62b0c6f7SStefano 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         }
347*62b0c6f7SStefano Zampini       } else {
348*62b0c6f7SStefano Zampini         /* every edge dofs should be connected trough a certain number of nodal dofs
349*62b0c6f7SStefano Zampini            to other edge dofs belonging to coarse edges
350*62b0c6f7SStefano Zampini            - at most 2 endpoints
351*62b0c6f7SStefano Zampini            - order-1 interior nodal dofs
352*62b0c6f7SStefano Zampini            - no undefined nodal dofs (nconn < order)
353*62b0c6f7SStefano Zampini         */
354*62b0c6f7SStefano Zampini         PetscInt ends = 0,ints = 0, undef = 0;
355*62b0c6f7SStefano Zampini         for (j=ii[i];j<ii[i+1];j++) {
356*62b0c6f7SStefano Zampini           PetscInt v = jj[j],k;
357*62b0c6f7SStefano Zampini           PetscInt nconn = iit[v+1]-iit[v];
358*62b0c6f7SStefano Zampini           for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--;
359*62b0c6f7SStefano Zampini           if (nconn > order) ends++;
360*62b0c6f7SStefano Zampini           else if (nconn == order) ints++;
361*62b0c6f7SStefano Zampini           else undef++;
362*62b0c6f7SStefano Zampini         }
363*62b0c6f7SStefano Zampini         if (undef || ends > 2 || ints != order -1) {
364*62b0c6f7SStefano Zampini           marks[cum++] = i;
365*62b0c6f7SStefano Zampini           ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
366*62b0c6f7SStefano Zampini           for (j=ii[i];j<ii[i+1];j++) {
367*62b0c6f7SStefano Zampini             ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
368*62b0c6f7SStefano Zampini           }
369*62b0c6f7SStefano Zampini         }
370*62b0c6f7SStefano 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   }
378*62b0c6f7SStefano 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);
381*62b0c6f7SStefano Zampini   if (!conforming) {
382*62b0c6f7SStefano Zampini     ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
383*62b0c6f7SStefano Zampini     ierr = MatDestroy(&lGt);CHKERRQ(ierr);
384*62b0c6f7SStefano 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   /* tell PCBDDC the topography has been analyzed */
1052a13144ffSStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
1053a13144ffSStefano Zampini 
1054a13144ffSStefano Zampini   /* set change of basis */
1055a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
1056a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1057a13144ffSStefano Zampini 
1058a13144ffSStefano Zampini   /* set quadratures */
1059a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
1060a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
1061a13144ffSStefano Zampini 
1062a13144ffSStefano Zampini   PetscFunctionReturn(0);
1063a13144ffSStefano Zampini }
1064a13144ffSStefano Zampini 
1065d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1066d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1067d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1068d8203eabSStefano Zampini #undef __FUNCT__
1069d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1070d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1071d8203eabSStefano Zampini {
1072d8203eabSStefano Zampini   PetscErrorCode ierr;
1073d8203eabSStefano Zampini   PetscInt       i;
1074d8203eabSStefano Zampini 
1075d8203eabSStefano Zampini   PetscFunctionBegin;
1076d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1077d8203eabSStefano Zampini     PetscInt first,last;
1078d8203eabSStefano Zampini 
1079d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
108086fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1081d8203eabSStefano Zampini     if (i>=first && i < last) {
1082d8203eabSStefano Zampini       PetscScalar *data;
1083d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1084d8203eabSStefano Zampini       if (!has_const) {
1085d8203eabSStefano Zampini         data[i-first] = 1.;
1086d8203eabSStefano Zampini       } else {
108786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
108886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1089d8203eabSStefano Zampini       }
1090d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1091d8203eabSStefano Zampini     }
1092d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1093d8203eabSStefano Zampini   }
1094d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1095d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1096d8203eabSStefano Zampini     PetscInt first,last;
1097d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1098d8203eabSStefano Zampini     if (i>=first && i < last) {
1099d8203eabSStefano Zampini       PetscScalar *data;
1100d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1101d8203eabSStefano Zampini       if (!has_const) {
1102d8203eabSStefano Zampini         data[i-first] = 0.;
1103d8203eabSStefano Zampini       } else {
110486fa73c5SStefano Zampini         data[2*i-first] = 0.;
110586fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1106d8203eabSStefano Zampini       }
1107d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1108d8203eabSStefano Zampini     }
1109d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1110d8203eabSStefano Zampini   }
1111d8203eabSStefano Zampini   PetscFunctionReturn(0);
1112d8203eabSStefano Zampini }
1113d8203eabSStefano Zampini 
1114669cc0f4SStefano Zampini #undef __FUNCT__
1115669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
11168ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1117669cc0f4SStefano Zampini {
1118a198735bSStefano Zampini   Mat                    loc_divudotp;
1119fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
11208ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1121669cc0f4SStefano Zampini   IS                     *faces,*edges;
1122669cc0f4SStefano Zampini   PetscScalar            *vals;
1123669cc0f4SStefano Zampini   const PetscScalar      *array;
1124669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
11251ae86dd6SStefano Zampini   PetscMPIInt            rank;
1126a198735bSStefano Zampini   PetscErrorCode         ierr;
1127669cc0f4SStefano Zampini 
1128669cc0f4SStefano Zampini   PetscFunctionBegin;
1129669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1130669cc0f4SStefano Zampini   if (graph->twodim) {
1131669cc0f4SStefano Zampini     lmaxneighs = 2;
1132669cc0f4SStefano Zampini   } else {
1133669cc0f4SStefano Zampini     lmaxneighs = 1;
1134669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1135669cc0f4SStefano Zampini       const PetscInt *idxs;
1136669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1137669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1138669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1139669cc0f4SStefano Zampini     }
1140669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1141669cc0f4SStefano Zampini   }
1142669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1143669cc0f4SStefano Zampini   maxsize = 0;
1144669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1145669cc0f4SStefano Zampini     PetscInt nn;
1146669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1147669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1148669cc0f4SStefano Zampini   }
1149669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1150669cc0f4SStefano Zampini     PetscInt nn;
1151669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1152669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1153669cc0f4SStefano Zampini   }
1154669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1155669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1156669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
11578ae0ca82SStefano Zampini   if (!transpose) {
11588ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
11598ae0ca82SStefano Zampini   } else {
11608ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
11618ae0ca82SStefano Zampini   }
1162669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
11631ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1164d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1165669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
11668ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1167669cc0f4SStefano Zampini   }
1168d8203eabSStefano Zampini 
1169669cc0f4SStefano Zampini   /* compute local quad vec */
1170a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
11718ae0ca82SStefano Zampini   if (!transpose) {
1172a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
11738ae0ca82SStefano Zampini   } else {
11748ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
11758ae0ca82SStefano Zampini   }
1176669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
11778ae0ca82SStefano Zampini   if (!transpose) {
1178a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
11798ae0ca82SStefano Zampini   } else {
11808ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
11818ae0ca82SStefano Zampini   }
1182fa23a32eSStefano Zampini   if (vl2l) {
1183fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1184fa23a32eSStefano Zampini   } else {
1185fa23a32eSStefano Zampini     vins = v;
1186fa23a32eSStefano Zampini   }
1187fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1188669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
11899a962809SStefano Zampini 
11901ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
11911ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1192669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1193669cc0f4SStefano Zampini     const PetscInt    *idxs;
1194669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1195669cc0f4SStefano Zampini 
1196669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1197669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1198669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
11991ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1200669cc0f4SStefano Zampini     idx = -(idx+1);
1201669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1202669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1203669cc0f4SStefano Zampini   }
1204669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1205669cc0f4SStefano Zampini     const PetscInt    *idxs;
1206669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1207669cc0f4SStefano Zampini 
1208669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1209669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1210669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
12111ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1212669cc0f4SStefano Zampini     idx = -(idx+1);
1213669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1214669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1215669cc0f4SStefano Zampini   }
1216c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1217fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1218fa23a32eSStefano Zampini   if (vl2l) {
1219fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1220fa23a32eSStefano Zampini   }
1221669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1222669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1223669cc0f4SStefano Zampini 
1224669cc0f4SStefano Zampini   /* assemble near null space */
1225669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1226669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1227669cc0f4SStefano Zampini   }
1228669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1229669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1230669cc0f4SStefano Zampini   }
1231669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1232669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1233669cc0f4SStefano Zampini }
1234669cc0f4SStefano Zampini 
1235669cc0f4SStefano Zampini 
1236a3df083aSStefano Zampini #undef __FUNCT__
12371f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
12381f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
12391f4df5f7SStefano Zampini {
12401f4df5f7SStefano Zampini   PetscErrorCode ierr;
12411f4df5f7SStefano Zampini   Vec            local,global;
12421f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12431f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
12441f4df5f7SStefano Zampini 
12451f4df5f7SStefano Zampini   PetscFunctionBegin;
12461f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
12471f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
12481f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
12491f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
12501f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
12511f4df5f7SStefano Zampini       PetscInt i;
12521f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12531f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
12541f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12551f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12561f4df5f7SStefano Zampini       }
12571f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
12581f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
12591f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
12601f4df5f7SStefano Zampini     }
12611f4df5f7SStefano Zampini   } else {
1262986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
12631f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1264986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1265986cdee1SStefano Zampini       if (i > 1) {
1266986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
12671f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12681f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12691f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12701f4df5f7SStefano Zampini         }
12711f4df5f7SStefano Zampini       }
12721f4df5f7SStefano Zampini     }
1273986cdee1SStefano Zampini   }
12741f4df5f7SStefano Zampini 
12751f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
12761f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
12771f4df5f7SStefano Zampini   }
12781f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
12791f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
12801f4df5f7SStefano Zampini   }
12811f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
12821f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
12831f4df5f7SStefano Zampini   }
12841f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
12851f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
12861f4df5f7SStefano Zampini   PetscFunctionReturn(0);
12871f4df5f7SStefano Zampini }
12881f4df5f7SStefano Zampini 
12891f4df5f7SStefano Zampini #undef __FUNCT__
12903e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
12913e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
12923e589ea0SStefano Zampini {
12933e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
12943e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
12953e589ea0SStefano Zampini   PetscErrorCode    ierr;
12963e589ea0SStefano Zampini 
12973e589ea0SStefano Zampini   PetscFunctionBegin;
12983e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
12993e589ea0SStefano Zampini     PetscFunctionReturn(0);
13003e589ea0SStefano Zampini   }
13013e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
13023e589ea0SStefano Zampini     Vec swap;
13033e589ea0SStefano Zampini 
13043e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
13053e589ea0SStefano Zampini     swap = pcbddc->work_change;
13063e589ea0SStefano Zampini     pcbddc->work_change = r;
13073e589ea0SStefano Zampini     r = swap;
13083e589ea0SStefano Zampini   }
13093e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13103e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13113e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13123e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
13133e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13143e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13153e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
13163e589ea0SStefano Zampini     Vec swap;
13173e589ea0SStefano Zampini 
13183e589ea0SStefano Zampini     swap = r;
13193e589ea0SStefano Zampini     r = pcbddc->work_change;
13203e589ea0SStefano Zampini     pcbddc->work_change = swap;
13213e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
13223e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
13233e589ea0SStefano Zampini   }
13243e589ea0SStefano Zampini   PetscFunctionReturn(0);
13253e589ea0SStefano Zampini }
13263e589ea0SStefano Zampini 
13273e589ea0SStefano Zampini #undef __FUNCT__
1328a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1329a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1330a3df083aSStefano Zampini {
1331a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1332a3df083aSStefano Zampini   PetscErrorCode          ierr;
1333a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1334a3df083aSStefano Zampini 
1335a3df083aSStefano Zampini   PetscFunctionBegin;
1336a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1337a3df083aSStefano Zampini   if (transpose) {
1338a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1339a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1340a3df083aSStefano Zampini   } else {
1341a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1342a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1343a3df083aSStefano Zampini   }
1344a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1345a3df083aSStefano Zampini   if (apply_right) {
1346a3df083aSStefano Zampini     const PetscScalar *ax;
1347a3df083aSStefano Zampini     PetscInt          nl,i;
1348a3df083aSStefano Zampini 
1349a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1350a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1351a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1352a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1353a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1354a3df083aSStefano Zampini       PetscScalar    sum,val;
1355a3df083aSStefano Zampini       const PetscInt *idxs;
1356a3df083aSStefano Zampini       PetscInt       nz,j;
1357a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1358a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1359a3df083aSStefano Zampini       sum = 0.;
1360a3df083aSStefano Zampini       if (ctx->apply_p0) {
1361a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1362a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1363a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1364a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1365a3df083aSStefano Zampini         }
1366a3df083aSStefano Zampini       } else {
1367a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1368a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1369a3df083aSStefano Zampini         }
1370a3df083aSStefano Zampini       }
1371a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1372a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1373a3df083aSStefano Zampini     }
1374a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1375a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1376a3df083aSStefano Zampini   }
1377a3df083aSStefano Zampini   if (transpose) {
1378a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1379a3df083aSStefano Zampini   } else {
1380a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1381a3df083aSStefano Zampini   }
1382a3df083aSStefano Zampini   if (reset_x) {
1383a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1384a3df083aSStefano Zampini   }
1385a3df083aSStefano Zampini   if (apply_left) {
1386a3df083aSStefano Zampini     PetscScalar *ay;
1387a3df083aSStefano Zampini     PetscInt    i;
1388a3df083aSStefano Zampini 
1389a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1390a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1391a3df083aSStefano Zampini       PetscScalar    sum,val;
1392a3df083aSStefano Zampini       const PetscInt *idxs;
1393a3df083aSStefano Zampini       PetscInt       nz,j;
1394a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1395a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1396a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1397a3df083aSStefano Zampini       if (ctx->apply_p0) {
1398a3df083aSStefano Zampini         sum = 0.;
1399a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1400a3df083aSStefano Zampini           sum += ay[idxs[j]];
1401a3df083aSStefano Zampini           ay[idxs[j]] += val;
1402a3df083aSStefano Zampini         }
1403a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1404a3df083aSStefano Zampini       } else {
1405a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1406a3df083aSStefano Zampini           ay[idxs[j]] += val;
1407a3df083aSStefano Zampini         }
1408a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1409a3df083aSStefano Zampini       }
1410a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1411a3df083aSStefano Zampini     }
1412a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1413a3df083aSStefano Zampini   }
1414a3df083aSStefano Zampini   PetscFunctionReturn(0);
1415a3df083aSStefano Zampini }
1416a3df083aSStefano Zampini 
1417a3df083aSStefano Zampini #undef __FUNCT__
1418a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1419a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1420a3df083aSStefano Zampini {
1421a3df083aSStefano Zampini   PetscErrorCode ierr;
1422a3df083aSStefano Zampini 
1423a3df083aSStefano Zampini   PetscFunctionBegin;
1424a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1425a3df083aSStefano Zampini   PetscFunctionReturn(0);
1426a3df083aSStefano Zampini }
1427a3df083aSStefano Zampini 
1428a3df083aSStefano Zampini #undef __FUNCT__
1429a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1430a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1431a3df083aSStefano Zampini {
1432a3df083aSStefano Zampini   PetscErrorCode ierr;
1433a3df083aSStefano Zampini 
1434a3df083aSStefano Zampini   PetscFunctionBegin;
1435a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1436a3df083aSStefano Zampini   PetscFunctionReturn(0);
1437a3df083aSStefano Zampini }
1438a3df083aSStefano Zampini 
1439a3df083aSStefano Zampini #undef __FUNCT__
1440a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1441a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1442a3df083aSStefano Zampini {
1443a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1444a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1445a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1446a3df083aSStefano Zampini   PetscErrorCode          ierr;
1447a3df083aSStefano Zampini 
1448a3df083aSStefano Zampini   PetscFunctionBegin;
1449a3df083aSStefano Zampini   if (!restore) {
14501dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1451a3df083aSStefano Zampini     PetscScalar        *work;
1452b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1453a3df083aSStefano Zampini 
14549a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
14559a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1456a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1457a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1458a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1459a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1460a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1461a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1462a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1463a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1464a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1465a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1466a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1467a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1468059032f7SStefano Zampini     if (reuse) {
1469a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
14701dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1471059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1472059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1473059032f7SStefano Zampini       PetscInt               i;
1474059032f7SStefano Zampini 
1475059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1476059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1477059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1478059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1479059032f7SStefano Zampini       }
1480059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
14811dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1482059032f7SStefano Zampini     }
1483a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1484a3df083aSStefano Zampini     ctx->work = work;
1485a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1486a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1487a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1488a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1489a3df083aSStefano Zampini 
1490a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1491a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1492a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1493a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1494a3df083aSStefano Zampini   } else {
14951dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
14961dd7afcfSStefano Zampini       PetscFunctionReturn(0);
14971dd7afcfSStefano Zampini     }
1498a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1499a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1500a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
15011dd7afcfSStefano Zampini     ctx->A = NULL;
15021dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
15031dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
15041dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
15051dd7afcfSStefano Zampini     if (ctx->free) {
1506059032f7SStefano Zampini       PetscInt i;
15071dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1508059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1509059032f7SStefano Zampini       }
1510059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1511059032f7SStefano Zampini     }
1512a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1513a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1514a3df083aSStefano Zampini   }
1515a3df083aSStefano Zampini   PetscFunctionReturn(0);
1516a3df083aSStefano Zampini }
1517a3df083aSStefano Zampini 
1518a3df083aSStefano Zampini /* used just in bddc debug mode */
1519a3df083aSStefano Zampini #undef __FUNCT__
1520a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1521a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1522a3df083aSStefano Zampini {
1523a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1524a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1525a3df083aSStefano Zampini   Mat            An;
1526a3df083aSStefano Zampini   PetscErrorCode ierr;
1527a3df083aSStefano Zampini 
1528a3df083aSStefano Zampini   PetscFunctionBegin;
1529a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1530a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1531a3df083aSStefano Zampini   if (is1) {
1532a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1533a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1534a3df083aSStefano Zampini   } else {
1535a3df083aSStefano Zampini     *B = An;
1536a3df083aSStefano Zampini   }
1537a3df083aSStefano Zampini   PetscFunctionReturn(0);
1538a3df083aSStefano Zampini }
1539a3df083aSStefano Zampini 
15401cf9b237SStefano Zampini /* TODO: add reuse flag */
15411cf9b237SStefano Zampini #undef __FUNCT__
15421cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
15431cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
15441cf9b237SStefano Zampini {
15451cf9b237SStefano Zampini   Mat            Bt;
15461cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
15471cf9b237SStefano Zampini   const PetscInt *ii,*ij;
15481cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
15491cf9b237SStefano Zampini   PetscBool      flg_row;
15501cf9b237SStefano Zampini   PetscErrorCode ierr;
15511cf9b237SStefano Zampini 
15521cf9b237SStefano Zampini   PetscFunctionBegin;
15531cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
15541cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15551cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
15561cf9b237SStefano Zampini   nnz = n;
15571cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
15581cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
15591cf9b237SStefano Zampini   }
15601cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
15611cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
15621cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
15631cf9b237SStefano Zampini   nnz = 0;
15641cf9b237SStefano Zampini   bii[0] = 0;
15651cf9b237SStefano Zampini   for (i=0;i<n;i++) {
15661cf9b237SStefano Zampini     PetscInt j;
15671cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
15681cf9b237SStefano Zampini       PetscScalar entry = a[j];
15691cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
15701cf9b237SStefano Zampini         bij[nnz] = ij[j];
15711cf9b237SStefano Zampini         bdata[nnz] = entry;
15721cf9b237SStefano Zampini         nnz++;
15731cf9b237SStefano Zampini       }
15741cf9b237SStefano Zampini     }
15751cf9b237SStefano Zampini     bii[i+1] = nnz;
15761cf9b237SStefano Zampini   }
15771cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
15781cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
15791cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15801cf9b237SStefano Zampini   {
15811cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
15821cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
15831cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
15841cf9b237SStefano Zampini   }
15851cf9b237SStefano Zampini   *B = Bt;
15861cf9b237SStefano Zampini   PetscFunctionReturn(0);
15871cf9b237SStefano Zampini }
15881cf9b237SStefano Zampini 
1589674ae819SStefano Zampini #undef __FUNCT__
15904f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
15914f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
15924f1b2e48SStefano Zampini {
15934f1b2e48SStefano Zampini   Mat                    B;
15944f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
15954f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
15964f1b2e48SStefano Zampini   PCBDDCGraph            graph;
15974f1b2e48SStefano Zampini   PetscInt               i,n;
15984f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
15994f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
16004f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
16014f1b2e48SStefano Zampini   PetscErrorCode         ierr;
16024f1b2e48SStefano Zampini 
16034f1b2e48SStefano Zampini   PetscFunctionBegin;
160463c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
160563c961adSStefano Zampini     *ncc = 0;
160663c961adSStefano Zampini     *cc = NULL;
160763c961adSStefano Zampini     PetscFunctionReturn(0);
160863c961adSStefano Zampini   }
16094f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
16104f1b2e48SStefano Zampini   if (!isseqaij && filter) {
16111cf9b237SStefano Zampini     PetscBool isseqdense;
16121cf9b237SStefano Zampini 
16131cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
16141cf9b237SStefano Zampini     if (!isseqdense) {
16154f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
16161cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
16171cf9b237SStefano Zampini       PetscScalar *array;
16181cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
16191cf9b237SStefano Zampini 
16201cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
16211cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
16221cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
16231cf9b237SStefano Zampini       for (i=0;i<n;i++) {
16241cf9b237SStefano Zampini         PetscInt j;
16251cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
16261cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
16271cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
16281cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
16291cf9b237SStefano Zampini         }
16301cf9b237SStefano Zampini       }
16311cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
16329d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
16331cf9b237SStefano Zampini     }
16344f1b2e48SStefano Zampini   } else {
16354f1b2e48SStefano Zampini     B = A;
16364f1b2e48SStefano Zampini   }
16374f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16384f1b2e48SStefano Zampini 
16394f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
16404f1b2e48SStefano Zampini   if (filter) {
16414f1b2e48SStefano Zampini     PetscScalar *data;
16424f1b2e48SStefano Zampini     PetscInt    j,cum;
16434f1b2e48SStefano Zampini 
16444f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
16454f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
16464f1b2e48SStefano Zampini     cum = 0;
16474f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
16484f1b2e48SStefano Zampini       PetscInt t;
16494f1b2e48SStefano Zampini 
16504f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
16514f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
16524f1b2e48SStefano Zampini           continue;
16534f1b2e48SStefano Zampini         }
16544f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
16554f1b2e48SStefano Zampini       }
16564f1b2e48SStefano Zampini       t = xadj_filtered[i];
16574f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
16584f1b2e48SStefano Zampini       cum += t;
16594f1b2e48SStefano Zampini     }
16604f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
16614f1b2e48SStefano Zampini   } else {
16624f1b2e48SStefano Zampini     xadj_filtered = NULL;
16634f1b2e48SStefano Zampini     adjncy_filtered = NULL;
16644f1b2e48SStefano Zampini   }
16654f1b2e48SStefano Zampini 
16664f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
16674f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
16684f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
16694f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
16704f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1671be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
16724f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
16734f1b2e48SStefano Zampini   if (xadj_filtered) {
16744f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
16754f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
16764f1b2e48SStefano Zampini   } else {
16774f1b2e48SStefano Zampini     graph->xadj = xadj;
16784f1b2e48SStefano Zampini     graph->adjncy = adjncy;
16794f1b2e48SStefano Zampini   }
16804f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
16814f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
16824f1b2e48SStefano Zampini   /* partial clean up */
16834f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
16844f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16851cf9b237SStefano Zampini   if (A != B) {
16864f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
16874f1b2e48SStefano Zampini   }
16884f1b2e48SStefano Zampini 
16894f1b2e48SStefano Zampini   /* get back data */
16901cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
16911cf9b237SStefano Zampini   if (cc) {
16924f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
16934f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
16944f1b2e48SStefano 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);
16954f1b2e48SStefano Zampini     }
16964f1b2e48SStefano Zampini     *cc = cc_n;
16971cf9b237SStefano Zampini   }
16984f1b2e48SStefano Zampini   /* clean up graph */
16994f1b2e48SStefano Zampini   graph->xadj = 0;
17004f1b2e48SStefano Zampini   graph->adjncy = 0;
17014f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
17024f1b2e48SStefano Zampini   PetscFunctionReturn(0);
17034f1b2e48SStefano Zampini }
17044f1b2e48SStefano Zampini 
17054f1b2e48SStefano Zampini #undef __FUNCT__
17065408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
17075408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
17085408967cSStefano Zampini {
17095408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17105408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1711dee84bffSStefano Zampini   IS             dirIS = NULL;
17124f1b2e48SStefano Zampini   PetscInt       i;
17135408967cSStefano Zampini   PetscErrorCode ierr;
17145408967cSStefano Zampini 
17155408967cSStefano Zampini   PetscFunctionBegin;
1716dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
17175408967cSStefano Zampini   if (zerodiag) {
17185408967cSStefano Zampini     Mat            A;
17195408967cSStefano Zampini     Vec            vec3_N;
17205408967cSStefano Zampini     PetscScalar    *vals;
17215408967cSStefano Zampini     const PetscInt *idxs;
1722d12d3064SStefano Zampini     PetscInt       nz,*count;
17235408967cSStefano Zampini 
17245408967cSStefano Zampini     /* p0 */
17255408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
17265408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
17275408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17285408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17294f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
17305408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17315408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
17325408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
17335408967cSStefano Zampini     /* v_I */
17345408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
17355408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
17365408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17375408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
17385408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17395408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
17405408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17415408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17425408967cSStefano Zampini     if (dirIS) {
17435408967cSStefano Zampini       PetscInt n;
17445408967cSStefano Zampini 
17455408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
17465408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
17475408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
17485408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17495408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
17505408967cSStefano Zampini     }
17515408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
17525408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
17535408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
17545408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1755669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
17565408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
17575408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
17589a962809SStefano 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]));
17595408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
17605408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1761d12d3064SStefano Zampini 
1762d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1763d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1764d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1765d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1766d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1767d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17689a962809SStefano 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]);
1769d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1770d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
17715408967cSStefano Zampini   }
1772dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
17735408967cSStefano Zampini 
17745408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
17755408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
17764f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
17775408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
17784f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
17795408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1780f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1781f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1782f2a566d8SStefano 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);
1783f2a566d8SStefano Zampini   }
17845408967cSStefano Zampini   PetscFunctionReturn(0);
17855408967cSStefano Zampini }
17865408967cSStefano Zampini 
17875408967cSStefano Zampini #undef __FUNCT__
1788339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1789339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1790339f8db1SStefano Zampini {
1791339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17924f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1793b0f5fe93SStefano Zampini   PetscInt       nz,n;
17941f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
17954f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1796339f8db1SStefano Zampini   PetscErrorCode ierr;
1797339f8db1SStefano Zampini 
1798339f8db1SStefano Zampini   PetscFunctionBegin;
17999f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
18009f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1801a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1802a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1803a3df083aSStefano Zampini   }
1804a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1805a3df083aSStefano Zampini   pcbddc->benign_n = 0;
18061ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
18074f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
18084f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
18094f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
18101ae86dd6SStefano Zampini      since the local Schur complements are already SPD
18114f1b2e48SStefano Zampini   */
18124f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
18134f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
181440fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
18154f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
18164f1b2e48SStefano Zampini 
18174f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
18184f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
18194f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
18204f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1821ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
182240fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
182340fa8d13SStefano Zampini     if (!sorted) {
182440fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
182540fa8d13SStefano Zampini     }
182640fa8d13SStefano Zampini   } else {
182740fa8d13SStefano Zampini     pressures = NULL;
182840fa8d13SStefano Zampini   }
182997d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
183097d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
183127b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
183297d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1833339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1834339f8db1SStefano Zampini   if (!sorted) {
1835339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1836339f8db1SStefano Zampini   }
1837339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
18384f1b2e48SStefano Zampini   if (!nz) {
18394f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
18404f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
184140fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
184240fa8d13SStefano Zampini   }
18434f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
18444f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
18454f1b2e48SStefano Zampini   zerodiag_subs = NULL;
18464f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
18471f4df5f7SStefano Zampini   n_interior_dofs = 0;
18481f4df5f7SStefano Zampini   interior_dofs = NULL;
18491f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
18501f4df5f7SStefano Zampini     PetscInt n,i,j;
18511f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
18521f4df5f7SStefano Zampini     PetscInt *iwork;
18531f4df5f7SStefano Zampini 
18541f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
18551f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18561f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
18571f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
185890648384SStefano Zampini     for (i=1;i<n_neigh;i++)
18591f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
18601f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
18611f4df5f7SStefano Zampini     for (i=0;i<n;i++)
18621f4df5f7SStefano Zampini       if (!iwork[i])
18631f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
18641f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
18651f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18661f4df5f7SStefano Zampini   }
18674f1b2e48SStefano Zampini   if (has_null_pressures) {
18684f1b2e48SStefano Zampini     IS             *subs;
18691f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
18701f4df5f7SStefano Zampini     const PetscInt *idxs;
18711f4df5f7SStefano Zampini     PetscScalar    *array;
18721f4df5f7SStefano Zampini     Vec            *work;
18731f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
18744f1b2e48SStefano Zampini 
18754f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
18764f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
18771f4df5f7SStefano 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) */
18781f4df5f7SStefano Zampini     if (pcbddc->current_level) {
18791f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
18801f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
18811f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
18821f4df5f7SStefano Zampini       /* work[0] = 1_p */
18831f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
18841f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
18851f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
18861f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
18871f4df5f7SStefano Zampini       /* work[0] = 1_v */
18881f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
18891f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
18901f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
18911f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
18921f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
18931f4df5f7SStefano Zampini     }
18944f1b2e48SStefano Zampini     if (nsubs > 1) {
18954f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
18964f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
18974f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
18984f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
18994f1b2e48SStefano Zampini         PetscInt               nl;
19004f1b2e48SStefano Zampini 
19014f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
19024f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
19034f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
19044f1b2e48SStefano Zampini         if (nl) {
19054f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
19064f1b2e48SStefano Zampini 
19071f4df5f7SStefano Zampini           if (pcbddc->current_level) {
19081f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
19091f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
19101f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
19111f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19121f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
19131f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19141f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
19151f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
19161f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
19171f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
19181f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
19191f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
19201f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19211f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
19221f4df5f7SStefano Zampini                 break;
19231f4df5f7SStefano Zampini               }
19241f4df5f7SStefano Zampini             }
19251f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
19261f4df5f7SStefano Zampini           }
19271f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
19281f4df5f7SStefano Zampini             IS       t_bc;
19291f4df5f7SStefano Zampini             PetscInt nzb;
19301f4df5f7SStefano Zampini 
19311f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
19321f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
19331f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
19341f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
19351f4df5f7SStefano Zampini           }
19361f4df5f7SStefano Zampini           if (valid && pressures) {
19374f1b2e48SStefano Zampini             IS t_pressure_subs;
19384f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
19394f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
19404f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
19414f1b2e48SStefano Zampini           }
19424f1b2e48SStefano Zampini           if (valid) {
19434f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
19444f1b2e48SStefano Zampini             pcbddc->benign_n++;
19454f1b2e48SStefano Zampini           } else {
19464f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
19474f1b2e48SStefano Zampini           }
19484f1b2e48SStefano Zampini         }
19494f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
19504f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
19514f1b2e48SStefano Zampini       }
19524f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
19534f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
19541f4df5f7SStefano Zampini 
19551f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
19561f4df5f7SStefano Zampini         PetscInt nzb;
19571f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
19581f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
19591f4df5f7SStefano Zampini       }
19601f4df5f7SStefano Zampini       if (valid && pressures) {
19614f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
19624f1b2e48SStefano Zampini       }
19631f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
19641f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
19651f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
19661f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19671f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
19681f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19691f4df5f7SStefano Zampini               valid = PETSC_FALSE;
19701f4df5f7SStefano Zampini               break;
19711f4df5f7SStefano Zampini           }
19721f4df5f7SStefano Zampini         }
19731f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19741f4df5f7SStefano Zampini       }
19754f1b2e48SStefano Zampini       if (valid) {
19764f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1977ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
19784f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
19794f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
19804f1b2e48SStefano Zampini       }
19814f1b2e48SStefano Zampini     }
19821f4df5f7SStefano Zampini     if (pcbddc->current_level) {
19831f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
19844f1b2e48SStefano Zampini     }
19851f4df5f7SStefano Zampini   }
19861f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
19874f1b2e48SStefano Zampini 
19884f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1989b9b0e38cSStefano Zampini     PetscInt n;
1990b9b0e38cSStefano Zampini 
19914f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
19924f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1993b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1994b9b0e38cSStefano Zampini     if (n) {
19954f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
19964f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
19974f1b2e48SStefano Zampini     }
1998b9b0e38cSStefano Zampini   }
19994f1b2e48SStefano Zampini 
20004f1b2e48SStefano Zampini   /* final check for null pressures */
20014f1b2e48SStefano Zampini   if (zerodiag && pressures) {
20024f1b2e48SStefano Zampini     PetscInt nz,np;
20034f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
20044f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
20054f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
20064f1b2e48SStefano Zampini   }
20074f1b2e48SStefano Zampini 
20084f1b2e48SStefano Zampini   if (recompute_zerodiag) {
20094f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
20104f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
20114f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
20124f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
20134f1b2e48SStefano Zampini     } else {
20144f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
20154f1b2e48SStefano Zampini 
20164f1b2e48SStefano Zampini       nzn = 0;
20174f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20184f1b2e48SStefano Zampini         PetscInt ns;
20194f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20204f1b2e48SStefano Zampini         nzn += ns;
20214f1b2e48SStefano Zampini       }
20224f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
20234f1b2e48SStefano Zampini       nzn = 0;
20244f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20254f1b2e48SStefano Zampini         PetscInt ns,*idxs;
20264f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
20274f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20284f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
20294f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
20304f1b2e48SStefano Zampini         nzn += ns;
20314f1b2e48SStefano Zampini       }
20324f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
20334f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
20344f1b2e48SStefano Zampini     }
20354f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
20364f1b2e48SStefano Zampini   }
20374f1b2e48SStefano Zampini 
2038669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
2039a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2040a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2041a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2042a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2043a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2044a198735bSStefano Zampini 
20451f4df5f7SStefano Zampini     if (pressures) {
20461f4df5f7SStefano Zampini       isused = pressures;
20471f4df5f7SStefano Zampini     } else {
20481f4df5f7SStefano Zampini       isused = zerodiag;
20491f4df5f7SStefano Zampini     }
2050a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2051669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
20521ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
20531ae86dd6SStefano 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");
2054a198735bSStefano Zampini     n_isused = 0;
2055a198735bSStefano Zampini     if (isused) {
2056a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2057a198735bSStefano Zampini     }
2058a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2059a198735bSStefano Zampini     st = st-n_isused;
20601ae86dd6SStefano Zampini     if (n) {
2061a198735bSStefano Zampini       const PetscInt *gidxs;
2062a198735bSStefano Zampini 
2063a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2064a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2065a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2066a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2067a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2068a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
20691ae86dd6SStefano Zampini     } else {
2070a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2071a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2072a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2073a198735bSStefano Zampini     }
2074a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2075a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2076a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2077a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2078a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2079a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2080a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2081a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2082a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2083a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2084a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2085a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2086a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2087a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
20881ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20891ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20901ae86dd6SStefano Zampini   }
2091b3afcdbeSStefano Zampini 
2092b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
20934f1b2e48SStefano Zampini   if (has_null_pressures) {
20944f1b2e48SStefano Zampini     IS             zerodiagc;
20954f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
20964f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
20974f1b2e48SStefano Zampini 
20984f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2099339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2100339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2101339f8db1SStefano Zampini     /* local change of basis for pressures */
2102339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
210397d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2104339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2105339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2106339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
21074f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
21084f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
21094f1b2e48SStefano Zampini       PetscInt nzs,j;
21104f1b2e48SStefano Zampini 
21114f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
21124f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21134f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
21144f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
21154f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
21164f1b2e48SStefano Zampini     }
2117339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2118339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2119339f8db1SStefano Zampini     /* set identity on velocities */
2120339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2121339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2122339f8db1SStefano Zampini     }
21234f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
21244f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
21259f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
21264f1b2e48SStefano 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);
2127339f8db1SStefano Zampini     /* set change on pressures */
21284f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
21294f1b2e48SStefano Zampini       PetscScalar *array;
21304f1b2e48SStefano Zampini       PetscInt    nzs;
21314f1b2e48SStefano Zampini 
21324f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
21334f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
21344f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2135339f8db1SStefano Zampini         PetscScalar vals[2];
2136339f8db1SStefano Zampini         PetscInt    cols[2];
2137339f8db1SStefano Zampini 
2138339f8db1SStefano Zampini         cols[0] = idxs[i];
21394f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2140339f8db1SStefano Zampini         vals[0] = 1.;
2141b0f5fe93SStefano Zampini         vals[1] = 1.;
21424f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2143339f8db1SStefano Zampini       }
21444f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
21454f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
21464f1b2e48SStefano Zampini       array[nzs-1] = 1.;
21474f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
21484f1b2e48SStefano Zampini       /* store local idxs for p0 */
21494f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
21504f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2151339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
21524f1b2e48SStefano Zampini     }
2153339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2154339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2155a3df083aSStefano Zampini     /* project if needed */
2156a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
21571dd7afcfSStefano Zampini       Mat M;
21581dd7afcfSStefano Zampini 
21591dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2160339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
21611dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
21621dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2163a3df083aSStefano Zampini     }
21644f1b2e48SStefano Zampini     /* store global idxs for p0 */
21654f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2166339f8db1SStefano Zampini   }
2167ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
21684f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2169b0f5fe93SStefano Zampini 
2170b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2171b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
217227b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
217327b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2174339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2175339f8db1SStefano Zampini   PetscFunctionReturn(0);
2176339f8db1SStefano Zampini }
2177339f8db1SStefano Zampini 
2178339f8db1SStefano Zampini #undef __FUNCT__
2179015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2180015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2181efc2fbd9SStefano Zampini {
2182efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2183de9d7bd0SStefano Zampini   PetscScalar    *array;
2184efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2185efc2fbd9SStefano Zampini 
2186efc2fbd9SStefano Zampini   PetscFunctionBegin;
2187efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2188efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
21894f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2190efc2fbd9SStefano Zampini   }
2191de9d7bd0SStefano Zampini   if (get) {
2192efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
21934f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
21944f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2195efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2196de9d7bd0SStefano Zampini   } else {
2197de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2198de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2199de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2200de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2201efc2fbd9SStefano Zampini   }
2202efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2203efc2fbd9SStefano Zampini }
2204efc2fbd9SStefano Zampini 
2205efc2fbd9SStefano Zampini #undef __FUNCT__
2206c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2207c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2208c263805aSStefano Zampini {
2209c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2210c263805aSStefano Zampini   PetscErrorCode ierr;
2211c263805aSStefano Zampini 
2212c263805aSStefano Zampini   PetscFunctionBegin;
2213c263805aSStefano Zampini   /* TODO: add error checking
2214c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2215c263805aSStefano Zampini     - cannot push before pop.
22161c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2217c263805aSStefano Zampini   */
22184f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2219efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2220efc2fbd9SStefano Zampini   }
2221c263805aSStefano Zampini   if (pop) {
2222a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22234f1b2e48SStefano Zampini       IS       is_p0;
22244f1b2e48SStefano Zampini       MatReuse reuse;
2225c263805aSStefano Zampini 
2226c263805aSStefano Zampini       /* extract B_0 */
22274f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
22284f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
22294f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
22304f1b2e48SStefano Zampini       }
22314f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
22324f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2233c263805aSStefano Zampini       /* remove rows and cols from local problem */
2234c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
223597d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
22364f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
22374f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2238a3df083aSStefano Zampini     } else {
2239a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2240a3df083aSStefano Zampini       PetscScalar *vals;
2241a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2242a3df083aSStefano Zampini 
2243a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2244a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2245a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
22460b5adadeSStefano Zampini         PetscInt *nnz;
2247a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2248a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2249a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2250331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2251331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2252331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2253331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2254331e053bSStefano Zampini         }
2255331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2256331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2257331e053bSStefano Zampini       }
2258a3df083aSStefano Zampini 
2259a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2260a3df083aSStefano Zampini         PetscScalar *array;
2261a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2262a3df083aSStefano Zampini 
2263a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2264a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2265a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2266a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2267a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2268a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2269a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2270a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2271a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2272a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2273a3df083aSStefano Zampini         cum = 0;
2274a3df083aSStefano Zampini         for (j=0;j<n;j++) {
227522db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2276a3df083aSStefano Zampini             vals[cum] = array[j];
2277a3df083aSStefano Zampini             idxs_ins[cum] = j;
2278a3df083aSStefano Zampini             cum++;
2279a3df083aSStefano Zampini           }
2280a3df083aSStefano Zampini         }
2281a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2282a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2283a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2284a3df083aSStefano Zampini       }
2285a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2286a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2287a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2288a3df083aSStefano Zampini     }
2289c263805aSStefano Zampini   } else { /* push */
2290a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22914f1b2e48SStefano Zampini       PetscInt i;
22924f1b2e48SStefano Zampini 
22934f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
22944f1b2e48SStefano Zampini         PetscScalar *B0_vals;
22954f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
22964f1b2e48SStefano Zampini 
22974f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22984f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
22997b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
23004f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
23014f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
23024f1b2e48SStefano Zampini       }
2303c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2304c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2305a3df083aSStefano Zampini     } else {
2306a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2307a3df083aSStefano Zampini     }
2308c263805aSStefano Zampini   }
2309c263805aSStefano Zampini   PetscFunctionReturn(0);
2310c263805aSStefano Zampini }
2311c263805aSStefano Zampini 
2312c263805aSStefano Zampini #undef __FUNCT__
2313b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
231408122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2315b1b3d7a2SStefano Zampini {
2316b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
231708122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
231808122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
231908122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
232008122e43SStefano Zampini   PetscScalar     *work,lwork;
232108122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
232208122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
232308122e43SStefano Zampini   PetscReal       *eigs,thresh;
23241b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2325f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
232608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
232708122e43SStefano Zampini   PetscReal       *rwork;
232808122e43SStefano Zampini #endif
2329b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2330b1b3d7a2SStefano Zampini 
2331b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2332b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2333af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2334af25d912SStefano 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);
233506a4e24aSStefano Zampini 
2336fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2337fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2338fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2339fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
23401575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2341fd14bc51SStefano Zampini   }
2342fd14bc51SStefano Zampini 
2343e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2344e496cd5dSStefano 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);
2345e496cd5dSStefano Zampini   }
2346e496cd5dSStefano Zampini 
234708122e43SStefano Zampini   /* max size of subsets */
234808122e43SStefano Zampini   mss = 0;
234908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
235008122e43SStefano Zampini     PetscInt subset_size;
2351862806e4SStefano Zampini 
235208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
235308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
235408122e43SStefano Zampini   }
235508122e43SStefano Zampini 
235608122e43SStefano Zampini   /* min/max and threshold */
235708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2358f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
235908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2360f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2361f6f667cfSStefano Zampini   if (nmin) {
2362f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2363f6f667cfSStefano Zampini   }
236408122e43SStefano Zampini 
236508122e43SStefano Zampini   /* allocate lapack workspace */
236608122e43SStefano Zampini   cum = cum2 = 0;
236708122e43SStefano Zampini   maxneigs = 0;
236808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
236908122e43SStefano Zampini     PetscInt n,subset_size;
2370f6f667cfSStefano Zampini 
237108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
237208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
23739162d606SStefano Zampini     cum += subset_size;
23749162d606SStefano Zampini     cum2 += subset_size*n;
237508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
237608122e43SStefano Zampini   }
237708122e43SStefano Zampini   if (mss) {
23789ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
237908122e43SStefano Zampini       PetscBLASInt B_itype = 1;
238008122e43SStefano Zampini       PetscBLASInt B_N = mss;
23814c6709b3SStefano Zampini       PetscReal    zero = 0.0;
23824c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
238308122e43SStefano Zampini 
238408122e43SStefano Zampini       B_lwork = -1;
238508122e43SStefano Zampini       S = NULL;
238608122e43SStefano Zampini       St = NULL;
2387a58a30b4SStefano Zampini       eigs = NULL;
2388a58a30b4SStefano Zampini       eigv = NULL;
2389a58a30b4SStefano Zampini       B_iwork = NULL;
2390a58a30b4SStefano Zampini       B_ifail = NULL;
2391d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2392d1710679SStefano Zampini       rwork = NULL;
2393d1710679SStefano Zampini #endif
23948bec7fa6SStefano Zampini       thresh = 1.0;
239508122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
239608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
239708122e43SStefano 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));
239808122e43SStefano Zampini #else
239908122e43SStefano 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));
240008122e43SStefano Zampini #endif
240108122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
240208122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
240308122e43SStefano Zampini     } else {
240408122e43SStefano Zampini         /* TODO */
240508122e43SStefano Zampini     }
240608122e43SStefano Zampini   } else {
240708122e43SStefano Zampini     lwork = 0;
240808122e43SStefano Zampini   }
240908122e43SStefano Zampini 
241008122e43SStefano Zampini   nv = 0;
2411d62866d3SStefano 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) */
2412d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
241308122e43SStefano Zampini   }
24144c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2415f6f667cfSStefano Zampini   if (allocated_S_St) {
2416f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2417f6f667cfSStefano Zampini   }
2418f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
241908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
242008122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
242108122e43SStefano Zampini #endif
24229162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
24239162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
24249162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
242508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
24269162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
242708122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
242808122e43SStefano Zampini 
242908122e43SStefano Zampini   maxneigs = 0;
243072b8c272SStefano Zampini   cum = cumarray = 0;
24319162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
24329162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2433d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
243408122e43SStefano Zampini     const PetscInt *idxs;
243508122e43SStefano Zampini 
2436d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
243708122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
243808122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
243908122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
244008122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
24419162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
24429162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
244308122e43SStefano Zampini     }
2444d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
244508122e43SStefano Zampini   }
244608122e43SStefano Zampini 
244708122e43SStefano Zampini   if (mss) { /* multilevel */
244808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
244908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
245008122e43SStefano Zampini   }
245108122e43SStefano Zampini 
2452ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
245308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
245408122e43SStefano Zampini     const PetscInt *idxs;
24559d54b7f4SStefano Zampini     PetscReal      upper,lower;
2456862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
245708122e43SStefano Zampini     PetscBLASInt   B_N;
2458aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
245908122e43SStefano Zampini 
24609d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
24619d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
24629d54b7f4SStefano Zampini       lower = thresh;
24639d54b7f4SStefano Zampini     } else {
24649d54b7f4SStefano Zampini       upper = 1./thresh;
24659d54b7f4SStefano Zampini       lower = 0.;
24669d54b7f4SStefano Zampini     }
2467862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2468ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2469f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2470f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
24719ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2472aff50787SStefano Zampini         PetscInt j,k;
2473aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2474aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2475aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
247608122e43SStefano Zampini         }
247708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2478aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2479aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2480aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2481aff50787SStefano Zampini           }
248208122e43SStefano Zampini         }
248308122e43SStefano Zampini       } else {
248408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
248608122e43SStefano Zampini       }
24878bec7fa6SStefano Zampini     } else {
2488f6f667cfSStefano Zampini       S = Sarray + cumarray;
2489f6f667cfSStefano Zampini       St = Starray + cumarray;
24908bec7fa6SStefano Zampini     }
2491aff50787SStefano Zampini     /* see if we can save some work */
2492b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2493aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2494aff50787SStefano Zampini     }
2495aff50787SStefano Zampini 
2496b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2497aff50787SStefano Zampini       B_neigs = 0;
2498aff50787SStefano Zampini     } else {
24999ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
250008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2501f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
25024c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
25039552c7c7SStefano Zampini         PetscInt     nmin_s;
2504b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
250508122e43SStefano Zampini 
2506fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
25078bec7fa6SStefano 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]]);
2508fd14bc51SStefano Zampini         }
2509d16cbb6bSStefano Zampini 
2510b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2511b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2512b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2513b7ab4a40SStefano Zampini         }
2514b7ab4a40SStefano Zampini 
251508122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2516b7ab4a40SStefano Zampini         if (compute_range) {
2517d16cbb6bSStefano Zampini 
2518d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
251908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25209d54b7f4SStefano 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));
252108122e43SStefano Zampini #else
25229d54b7f4SStefano 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));
252308122e43SStefano Zampini #endif
2524b7ab4a40SStefano Zampini         } else if (!same_data) {
2525d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2526d16cbb6bSStefano Zampini           B_IL = 1;
2527d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
25289d54b7f4SStefano 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));
2529d16cbb6bSStefano Zampini #else
25309d54b7f4SStefano 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));
2531d16cbb6bSStefano Zampini #endif
2532b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2533b7ab4a40SStefano Zampini           PetscInt k;
2534b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2535b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2536b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2537b7ab4a40SStefano Zampini           nmin = nmax;
2538b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2539b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2540b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2541b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2542b7ab4a40SStefano Zampini           }
2543d16cbb6bSStefano Zampini         }
254408122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
254508122e43SStefano Zampini         if (B_ierr) {
25466c4ed002SBarry 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);
25476c4ed002SBarry 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);
25486c4ed002SBarry 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);
254908122e43SStefano Zampini         }
255008122e43SStefano Zampini 
255108122e43SStefano Zampini         if (B_neigs > nmax) {
2552fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2553fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2554fd14bc51SStefano Zampini           }
25559d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
255608122e43SStefano Zampini           B_neigs = nmax;
255708122e43SStefano Zampini         }
255808122e43SStefano Zampini 
25599552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
25609552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
256108122e43SStefano Zampini           PetscBLASInt B_neigs2;
256208122e43SStefano Zampini 
25639d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2564f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
25659d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
25669d54b7f4SStefano Zampini           } else {
25679d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
25689d54b7f4SStefano Zampini             B_IU = nmin_s;
25699d54b7f4SStefano Zampini           }
2570fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2571fd14bc51SStefano 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);
2572fd14bc51SStefano Zampini           }
25739ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
25741ae86dd6SStefano Zampini             PetscInt j,k;
257508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
25761ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
25771ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
25781ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
257908122e43SStefano Zampini               }
258008122e43SStefano Zampini             }
258108122e43SStefano Zampini           } else {
258208122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258308122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
258408122e43SStefano Zampini           }
258508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
258608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25879d54b7f4SStefano 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));
258808122e43SStefano Zampini #else
25899d54b7f4SStefano 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));
259008122e43SStefano Zampini #endif
259108122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
259208122e43SStefano Zampini           B_neigs += B_neigs2;
259308122e43SStefano Zampini         }
259408122e43SStefano Zampini         if (B_ierr) {
25956c4ed002SBarry 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);
25966c4ed002SBarry 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);
25976c4ed002SBarry 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);
259808122e43SStefano Zampini         }
2599fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2600ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
260108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
260208122e43SStefano Zampini             if (eigs[j] == 0.0) {
2603ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
260408122e43SStefano Zampini             } else {
26059d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2606ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
26079d54b7f4SStefano Zampini               } else {
26089d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
26099d54b7f4SStefano Zampini               }
2610fd14bc51SStefano Zampini             }
261108122e43SStefano Zampini           }
261208122e43SStefano Zampini         }
261308122e43SStefano Zampini       } else {
261408122e43SStefano Zampini           /* TODO */
261508122e43SStefano Zampini       }
2616aff50787SStefano Zampini     }
26176c3e6151SStefano Zampini     /* change the basis back to the original one */
26186c3e6151SStefano Zampini     if (sub_schurs->change) {
261972b8c272SStefano Zampini       Mat change,phi,phit;
26206c3e6151SStefano Zampini 
26216c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26226c3e6151SStefano Zampini         PetscInt ii;
26236c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
26246c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26256c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2626684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2627684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2628684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2629684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2630684229deSStefano Zampini #else
26316c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2632684229deSStefano Zampini #endif
26336c3e6151SStefano Zampini           }
26346c3e6151SStefano Zampini         }
26356c3e6151SStefano Zampini       }
263672b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
26376c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
263872b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
26396c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
26406c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
26416c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
26426c3e6151SStefano Zampini     }
26438bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
26448bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
26459162d606SStefano Zampini     if (B_neigs) {
26469162d606SStefano 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);
2647fd14bc51SStefano Zampini 
2648fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26499552c7c7SStefano Zampini         PetscInt ii;
26509552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2651ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26529552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2653ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2654ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2655ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2656ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2657ac47001eSStefano Zampini #else
2658ac47001eSStefano 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);
2659ac47001eSStefano Zampini #endif
26609552c7c7SStefano Zampini           }
26619552c7c7SStefano Zampini         }
2662fd14bc51SStefano Zampini       }
26639162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
26649162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
26659162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
26669162d606SStefano Zampini       cum++;
266708122e43SStefano Zampini     }
266808122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
266908122e43SStefano Zampini     /* shift for next computation */
267008122e43SStefano Zampini     cumarray += subset_size*subset_size;
267108122e43SStefano Zampini   }
2672fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2673fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2674fd14bc51SStefano Zampini   }
267508122e43SStefano Zampini 
267608122e43SStefano Zampini   if (mss) {
267708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
267808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2679f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2680f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2681f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
268208122e43SStefano Zampini   }
2683f6f667cfSStefano Zampini   if (allocated_S_St) {
2684f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2685f6f667cfSStefano Zampini   }
2686f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
268708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
268808122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
268908122e43SStefano Zampini #endif
269008122e43SStefano Zampini   if (pcbddc->dbg_flag) {
26911b968477SStefano Zampini     PetscInt maxneigs_r;
2692b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
26939b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
269408122e43SStefano Zampini   }
269508122e43SStefano Zampini   PetscFunctionReturn(0);
269608122e43SStefano Zampini }
2697b1b3d7a2SStefano Zampini 
2698674ae819SStefano Zampini #undef __FUNCT__
2699c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2700c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2701c8587f34SStefano Zampini {
27028629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2703c8587f34SStefano Zampini   PetscErrorCode ierr;
2704c8587f34SStefano Zampini 
2705c8587f34SStefano Zampini   PetscFunctionBegin;
2706f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
27075e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2708c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2709c8587f34SStefano Zampini 
2710684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
27110fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2712684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2713c8587f34SStefano Zampini 
27148629588bSStefano Zampini   /*
27158629588bSStefano Zampini      Setup local correction and local part of coarse basis.
27168629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
27178629588bSStefano Zampini   */
271847f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
27198629588bSStefano Zampini 
27208629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
27218629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
27228629588bSStefano Zampini 
27238629588bSStefano Zampini   /* free */
27248629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2725c8587f34SStefano Zampini   PetscFunctionReturn(0);
2726c8587f34SStefano Zampini }
2727c8587f34SStefano Zampini 
2728c8587f34SStefano Zampini #undef __FUNCT__
2729674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2730674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2731674ae819SStefano Zampini {
2732674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2733674ae819SStefano Zampini   PetscErrorCode ierr;
2734674ae819SStefano Zampini 
2735674ae819SStefano Zampini   PetscFunctionBegin;
2736674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
273730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2738674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2739785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2740674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2741f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2742f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2743785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
274463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
274563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2746674ae819SStefano Zampini   PetscFunctionReturn(0);
2747674ae819SStefano Zampini }
2748674ae819SStefano Zampini 
2749674ae819SStefano Zampini #undef __FUNCT__
2750674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2751674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2752674ae819SStefano Zampini {
2753674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
27544f1b2e48SStefano Zampini   PetscInt       i;
2755674ae819SStefano Zampini   PetscErrorCode ierr;
2756674ae819SStefano Zampini 
2757674ae819SStefano Zampini   PetscFunctionBegin;
2758a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2759b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2760674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
276116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
27621dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2763674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2764669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2765fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2766a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2767674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
276871582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_FALSE;
27694f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
27704f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
27714f1b2e48SStefano Zampini   }
27724f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2773b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2774b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2775b334f244SStefano Zampini   }
2776674ae819SStefano Zampini   PetscFunctionReturn(0);
2777674ae819SStefano Zampini }
2778674ae819SStefano Zampini 
2779674ae819SStefano Zampini #undef __FUNCT__
2780674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2781674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2782674ae819SStefano Zampini {
2783674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2784674ae819SStefano Zampini   PetscErrorCode ierr;
2785674ae819SStefano Zampini 
2786674ae819SStefano Zampini   PetscFunctionBegin;
2787674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
278858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2789ca92afb2SStefano Zampini     PetscScalar *array;
279006656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
279106656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
279258da7f69SStefano Zampini   }
2793674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2794674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
279515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
279615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2797674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2798674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2799674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
280006656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2801674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2802674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28038ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2804674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2805674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2806674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2807f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2808f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2809f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2810f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2811727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
28120e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2813f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
281470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
281581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
28160369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
28171dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
28184f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
28198b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2820ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2821ca92afb2SStefano Zampini     PetscInt i;
2822ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2823ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2824ca92afb2SStefano Zampini     }
2825ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2826ca92afb2SStefano Zampini   }
28274f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2828674ae819SStefano Zampini   PetscFunctionReturn(0);
2829674ae819SStefano Zampini }
2830674ae819SStefano Zampini 
2831674ae819SStefano Zampini #undef __FUNCT__
2832f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2833f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
28346bfb1811SStefano Zampini {
28356bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
28366bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
28376bfb1811SStefano Zampini   VecType        impVecType;
28384f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
28396bfb1811SStefano Zampini   PetscErrorCode ierr;
28406bfb1811SStefano Zampini 
28416bfb1811SStefano Zampini   PetscFunctionBegin;
28426c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2843e7b262bdSStefano Zampini   /* get sizes */
28444f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2845b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
28466bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2847e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2848e7b262bdSStefano Zampini   /* R nodes */
2849e7b262bdSStefano Zampini   old_size = -1;
2850e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2851e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2852e7b262bdSStefano Zampini   }
2853e7b262bdSStefano Zampini   if (n_R != old_size) {
2854e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2855e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28566bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
28576bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
28586bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
28596bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2860e7b262bdSStefano Zampini   }
2861e7b262bdSStefano Zampini   /* local primal dofs */
2862e7b262bdSStefano Zampini   old_size = -1;
2863e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2864e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2865e7b262bdSStefano Zampini   }
2866e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2867e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
286883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2869e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
28706bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2871e7b262bdSStefano Zampini   }
2872e7b262bdSStefano Zampini   /* local explicit constraints */
2873e7b262bdSStefano Zampini   old_size = -1;
2874e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2875e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2876e7b262bdSStefano Zampini   }
2877e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2878e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
287983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
288083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
288183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
288283b7ccabSStefano Zampini   }
28836bfb1811SStefano Zampini   PetscFunctionReturn(0);
28846bfb1811SStefano Zampini }
28856bfb1811SStefano Zampini 
28866bfb1811SStefano Zampini #undef __FUNCT__
288747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
288847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
288988ebb749SStefano Zampini {
289025084f0cSStefano Zampini   PetscErrorCode  ierr;
289125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
289288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
289388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2894d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
289525084f0cSStefano Zampini   /* submatrices of local problem */
289680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
289706656605SStefano Zampini   /* submatrices of local coarse problem */
289806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
289925084f0cSStefano Zampini   /* working matrices */
290006656605SStefano Zampini   Mat             C_CR;
290125084f0cSStefano Zampini   /* additional working stuff */
290206656605SStefano Zampini   PC              pc_R;
29034f1b2e48SStefano Zampini   Mat             F;
29045cbda25cSStefano Zampini   Vec             dummy_vec;
2905a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
290625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
290706656605SStefano Zampini   PetscScalar     *work;
290806656605SStefano Zampini   PetscInt        *idx_V_B;
2909ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
291006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2911ffd830a3SStefano Zampini 
291225084f0cSStefano Zampini   /* some shortcuts to scalars */
291306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
291488ebb749SStefano Zampini 
291588ebb749SStefano Zampini   PetscFunctionBegin;
29169a962809SStefano 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");
2917ffd830a3SStefano Zampini 
2918ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2919b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29204f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2921b371cd4fSStefano Zampini   n_B = pcis->n_B;
2922b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
292388ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
292488ebb749SStefano Zampini 
292588ebb749SStefano Zampini   /* vertices in boundary numbering */
2926785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
29270e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
29286c4ed002SBarry 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);
292988ebb749SStefano Zampini 
293006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2931019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
293206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
293306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
293406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
293506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
293606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
293706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
293806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
293906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
294006656605SStefano Zampini 
294106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
294206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
294306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
294406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
294506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2946ffd830a3SStefano Zampini   lda_rhs = n_R;
2947a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
294806656605SStefano Zampini   if (isLU || isILU || isCHOL) {
294906656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2950b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2951df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2952d62866d3SStefano Zampini     MatFactorType      type;
2953d62866d3SStefano Zampini 
2954df4d28bfSStefano Zampini     F = reuse_solver->F;
29556816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2956d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2957ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
295822db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
295906656605SStefano Zampini   } else {
296006656605SStefano Zampini     F = NULL;
296106656605SStefano Zampini   }
296206656605SStefano Zampini 
2963ffd830a3SStefano Zampini   /* allocate workspace */
2964ffd830a3SStefano Zampini   n = 0;
2965ffd830a3SStefano Zampini   if (n_constraints) {
2966ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2967ffd830a3SStefano Zampini   }
2968ffd830a3SStefano Zampini   if (n_vertices) {
2969ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2970ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2971ffd830a3SStefano Zampini   }
2972ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2973ffd830a3SStefano Zampini 
29745cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
29755cbda25cSStefano Zampini   dummy_vec = NULL;
29765cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
29775cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
29785cbda25cSStefano Zampini   }
29795cbda25cSStefano Zampini 
298088ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
298188ebb749SStefano Zampini   if (n_constraints) {
298272b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
298306656605SStefano Zampini     IS          is_aux;
298480677318SStefano Zampini     PetscScalar *array,*array2;
298506656605SStefano Zampini 
2986f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
298780677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
298888ebb749SStefano Zampini 
298925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
299025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
29918ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
299272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
299388ebb749SStefano Zampini 
299480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
299580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2996ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
299788ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
299806656605SStefano Zampini       const PetscScalar *row_cmat_values;
299906656605SStefano Zampini       const PetscInt    *row_cmat_indices;
300006656605SStefano Zampini       PetscInt          size_of_constraint,j;
300188ebb749SStefano Zampini 
300206656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300306656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
3004ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
300506656605SStefano Zampini       }
300606656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
300706656605SStefano Zampini     }
3008ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
300906656605SStefano Zampini     if (F) {
301006656605SStefano Zampini       Mat B;
301106656605SStefano Zampini 
3012ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
3013a3df083aSStefano Zampini       if (need_benign_correction) {
3014df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3015a3df083aSStefano Zampini 
301672b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
301772b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
3018a3df083aSStefano Zampini       }
301980677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
3020a3df083aSStefano Zampini       if (need_benign_correction) {
3021a3df083aSStefano Zampini         PetscScalar        *marr;
3022df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3023a3df083aSStefano Zampini 
3024a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
30255cbda25cSStefano Zampini         if (lda_rhs != n_R) {
30265cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
30275cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30285cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
30295cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30305cbda25cSStefano Zampini           }
30315cbda25cSStefano Zampini         } else {
3032a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
3033a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30345cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3035a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3036a3df083aSStefano Zampini           }
30375cbda25cSStefano Zampini         }
3038a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
3039a3df083aSStefano Zampini       }
304006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
304106656605SStefano Zampini     } else {
304280677318SStefano Zampini       PetscScalar *marr;
304380677318SStefano Zampini 
304480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
304506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3046ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3047ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
304806656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
304906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
305006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
305106656605SStefano Zampini       }
305280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
305306656605SStefano Zampini     }
305480677318SStefano Zampini     if (!pcbddc->switch_static) {
305580677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
305680677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
305780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
305880677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3059ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
306080677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
306180677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
306280677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
306380677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
306480677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
306580677318SStefano Zampini       }
306680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
306780677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
306872b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
306980677318SStefano Zampini     } else {
3070ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3071ffd830a3SStefano Zampini         IS dummy;
3072ffd830a3SStefano Zampini 
3073ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
307472b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3075ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3076ffd830a3SStefano Zampini       } else {
307780677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
307880677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3079ffd830a3SStefano Zampini       }
308025084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
308180677318SStefano Zampini     }
308280677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
308380677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
308480677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
308506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
308606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
308780677318SStefano Zampini     if (isCHOL) {
308880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
308980677318SStefano Zampini     } else {
309025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
309180677318SStefano Zampini     }
309280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
309306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
309425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
309525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
309625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
309780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
309872b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
309972b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
310006656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
310106656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3102f4ddd8eeSStefano Zampini   }
3103fc227af8SStefano Zampini 
3104fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
310588ebb749SStefano Zampini   if (n_vertices) {
310606656605SStefano Zampini     IS is_aux;
31073a50541eSStefano Zampini 
3108b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
31096816873aSStefano Zampini       IS tis;
31106816873aSStefano Zampini 
31116816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
31126816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
31136816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
31146816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
31156816873aSStefano Zampini     } else {
31163a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
31176816873aSStefano Zampini     }
31189577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
31199577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
312004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
312125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
312288ebb749SStefano Zampini   }
312388ebb749SStefano Zampini 
312488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3125f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
312606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
312706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
312806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
312906656605SStefano Zampini     }
3130f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
313106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
313206656605SStefano Zampini       PetscScalar *marray;
313306656605SStefano Zampini 
313406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
313506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3136f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3137f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3138f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3139f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3140f4ddd8eeSStefano Zampini     }
3141f4ddd8eeSStefano Zampini   }
314206656605SStefano Zampini 
3143f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
314406656605SStefano Zampini     PetscScalar *marray;
314588ebb749SStefano Zampini 
314606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31478eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
314806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
314988ebb749SStefano Zampini     }
31503301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
315106656605SStefano Zampini       n *= 2;
315288ebb749SStefano Zampini     }
315306656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
315406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
315506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31568eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
315706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
315806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
315988ebb749SStefano Zampini     }
31603301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
316106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
31628eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
316306656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
316406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
316588ebb749SStefano Zampini       }
316688ebb749SStefano Zampini     } else {
3167c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3168c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
31691b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3170c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3171c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3172c0553b1fSStefano Zampini       }
317388ebb749SStefano Zampini     }
317406656605SStefano Zampini   }
3175019a44ceSStefano Zampini 
317606656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
31774f1b2e48SStefano Zampini   p0_lidx_I = NULL;
31784f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3179d12edf2fSStefano Zampini     const PetscInt *idxs;
3180d12edf2fSStefano Zampini 
3181d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
31824f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
31834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
31844f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
31854f1b2e48SStefano Zampini     }
3186d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3187d12edf2fSStefano Zampini   }
3188d16cbb6bSStefano Zampini 
318906656605SStefano Zampini   /* vertices */
319006656605SStefano Zampini   if (n_vertices) {
319116f15bc4SStefano Zampini 
3192af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
319304708bb6SStefano Zampini 
319416f15bc4SStefano Zampini     if (n_R) {
319514393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
319606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
319716f15bc4SStefano Zampini       PetscScalar  *x,*y;
319804708bb6SStefano Zampini       PetscBool    isseqaij;
319906656605SStefano Zampini 
320021eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
320114393ed6SStefano Zampini       if (need_benign_correction) {
320214393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
320314393ed6SStefano Zampini         IS                     is_p0;
320414393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
320514393ed6SStefano Zampini 
320614393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
320714393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
320814393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3209af25d912SStefano 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);
321014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
321114393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
321214393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
321314393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
321414393ed6SStefano Zampini       }
321514393ed6SStefano Zampini 
3216ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3217af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3218ffd830a3SStefano Zampini       } else {
3219ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3220ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3221ca92afb2SStefano Zampini         PetscInt       n;
3222ca92afb2SStefano Zampini         PetscBool      flg_row;
3223ffd830a3SStefano Zampini 
3224ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3225ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
32269d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3227ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3228ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3229ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3230ca92afb2SStefano Zampini           PetscInt j;
3231ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3232ffd830a3SStefano Zampini         }
3233ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3234ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3235ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3236ffd830a3SStefano Zampini       }
3237ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3238a3df083aSStefano Zampini       if (need_benign_correction) {
3239df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3240a3df083aSStefano Zampini         PetscScalar        *marr;
3241a3df083aSStefano Zampini 
3242a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
324314393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
324414393ed6SStefano Zampini 
324514393ed6SStefano Zampini                | 0 0  0 | (V)
324614393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
324714393ed6SStefano Zampini                | 0 0 -1 | (p0)
324814393ed6SStefano Zampini 
324914393ed6SStefano Zampini         */
3250df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
325114393ed6SStefano Zampini           const PetscScalar *vals;
325214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
325314393ed6SStefano Zampini           PetscInt          n,j,nz;
325414393ed6SStefano Zampini 
3255df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3256df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
325714393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
325814393ed6SStefano Zampini           for (j=0;j<n;j++) {
325914393ed6SStefano Zampini             PetscScalar val = vals[j];
326014393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
326114393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
326214393ed6SStefano Zampini           }
326314393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3264df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
326514393ed6SStefano Zampini         }
326672b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
326772b8c272SStefano Zampini       }
326872b8c272SStefano Zampini       if (F) {
326914393ed6SStefano Zampini         /* need to correct the rhs */
327072b8c272SStefano Zampini         if (need_benign_correction) {
327172b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
327272b8c272SStefano Zampini           PetscScalar        *marr;
327372b8c272SStefano Zampini 
327472b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
32755cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32765cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32775cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32785cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
32795cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32805cbda25cSStefano Zampini             }
32815cbda25cSStefano Zampini           } else {
3282a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3283a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
32845cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3285a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3286a3df083aSStefano Zampini             }
32875cbda25cSStefano Zampini           }
3288a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3289a3df083aSStefano Zampini         }
329006656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
329114393ed6SStefano Zampini         /* need to correct the solution */
3292a3df083aSStefano Zampini         if (need_benign_correction) {
3293df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3294a3df083aSStefano Zampini           PetscScalar        *marr;
3295a3df083aSStefano Zampini 
3296a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
32975cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32985cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32995cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
33005cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
33015cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
33025cbda25cSStefano Zampini             }
33035cbda25cSStefano Zampini           } else {
3304a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3305a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
33065cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3307a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3308a3df083aSStefano Zampini             }
33095cbda25cSStefano Zampini           }
3310a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3311a3df083aSStefano Zampini         }
331206656605SStefano Zampini       } else {
331306656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
331406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3315ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3316ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
331706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
331806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
331906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
332006656605SStefano Zampini         }
332106656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
332206656605SStefano Zampini       }
332380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3324ffd830a3SStefano Zampini       /* S_VV and S_CV */
332506656605SStefano Zampini       if (n_constraints) {
332606656605SStefano Zampini         Mat B;
332780677318SStefano Zampini 
3328ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
332980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3330ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3331ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
333280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
333580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
333680677318SStefano Zampini         }
3337ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
333880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
333980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3340ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
334180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
334206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3343ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3344ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
334506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
334606656605SStefano Zampini       }
334704708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
334804708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3349511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
335004708bb6SStefano Zampini       }
3351ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3352ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3353ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3354ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3355ffd830a3SStefano Zampini       }
335606656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
335714393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
335814393ed6SStefano Zampini       if (need_benign_correction) {
3359df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
336014393ed6SStefano Zampini         PetscScalar      *marr,*sums;
336114393ed6SStefano Zampini 
336214393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
336314393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3364df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
336514393ed6SStefano Zampini           const PetscScalar *vals;
336614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
336714393ed6SStefano Zampini           PetscInt          n,j,nz;
336814393ed6SStefano Zampini 
3369df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3370df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
337114393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
337214393ed6SStefano Zampini             PetscInt k;
337314393ed6SStefano Zampini             sums[j] = 0.;
337414393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
337514393ed6SStefano Zampini           }
337614393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
337714393ed6SStefano Zampini           for (j=0;j<n;j++) {
337814393ed6SStefano Zampini             PetscScalar val = vals[j];
337914393ed6SStefano Zampini             PetscInt k;
338014393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
338114393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
338214393ed6SStefano Zampini             }
338314393ed6SStefano Zampini           }
338414393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3385df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
338614393ed6SStefano Zampini         }
338714393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
338814393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
338914393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
339014393ed6SStefano Zampini       }
339180677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
339206656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
339306656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
339406656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
339506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
339606656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
339706656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
339806656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3399d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3400019a44ceSStefano Zampini     } else {
3401d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3402d16cbb6bSStefano Zampini     }
340321eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3404d16cbb6bSStefano Zampini 
340506656605SStefano Zampini     /* coarse basis functions */
340606656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
340716f15bc4SStefano Zampini       PetscScalar *y;
340816f15bc4SStefano Zampini 
3409ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
341006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
341106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
341206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341406656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
341506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
341606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
341706656605SStefano Zampini 
341806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34194f1b2e48SStefano Zampini         PetscInt j;
34204f1b2e48SStefano Zampini 
342106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
342206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
342306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34264f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
342706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
342806656605SStefano Zampini       }
342906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
343006656605SStefano Zampini     }
343104708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
343204708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
343306656605SStefano Zampini   }
34345cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
343506656605SStefano Zampini 
343606656605SStefano Zampini   if (n_constraints) {
343706656605SStefano Zampini     Mat B;
343806656605SStefano Zampini 
3439ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
344006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
344180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
344206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
344306656605SStefano Zampini     if (n_vertices) {
344480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
344580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
344680677318SStefano Zampini       } else {
344780677318SStefano Zampini         Mat S_VCt;
344880677318SStefano Zampini 
3449ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3450ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
345172b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3452ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3453ffd830a3SStefano Zampini         }
345480677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
345580677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
345680677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
345780677318SStefano Zampini       }
345806656605SStefano Zampini     }
345906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
346006656605SStefano Zampini     /* coarse basis functions */
346106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
346206656605SStefano Zampini       PetscScalar *y;
346306656605SStefano Zampini 
3464ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
346506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
346606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
346706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
347006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
347106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34724f1b2e48SStefano Zampini         PetscInt j;
34734f1b2e48SStefano Zampini 
347406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
347506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
347606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
347806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34794f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
348006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
348106656605SStefano Zampini       }
348206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
348306656605SStefano Zampini     }
348406656605SStefano Zampini   }
348580677318SStefano Zampini   if (n_constraints) {
348680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
348780677318SStefano Zampini   }
34884f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
348972b8c272SStefano Zampini 
349072b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
349172b8c272SStefano Zampini   if (pcbddc->benign_n) {
349272b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
349372b8c272SStefano Zampini     IS          is_dummy;
349472b8c272SStefano Zampini     PetscScalar *data;
349572b8c272SStefano Zampini     PetscInt    j;
349672b8c272SStefano Zampini 
349772b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
349872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
349972b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
350072b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
350186c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
350272b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
350372b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
350472b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
350572b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
350672b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
350772b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
350872b8c272SStefano Zampini       }
350972b8c272SStefano Zampini     }
351072b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
351172b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
351272b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
351372b8c272SStefano Zampini   }
3514019a44ceSStefano Zampini 
351506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
35163301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3517ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3518ffd830a3SStefano Zampini     PetscScalar *marray;
351906656605SStefano Zampini 
352006656605SStefano Zampini     if (n_constraints) {
3521ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
352206656605SStefano Zampini 
3523af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
352406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3525ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
352616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
352706656605SStefano Zampini       if (n_vertices) {
3528ffd830a3SStefano Zampini         Mat S_VCT;
352906656605SStefano Zampini 
353006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3531ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
353216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
353306656605SStefano Zampini       }
3534ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
35355b782168SStefano Zampini     } else {
35365b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
353706656605SStefano Zampini     }
353816f15bc4SStefano Zampini     if (n_vertices && n_R) {
3539ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3540ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3541ffd830a3SStefano Zampini       PetscInt       n;
3542ffd830a3SStefano Zampini       PetscBool      flg_row;
354306656605SStefano Zampini 
3544ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3545af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3546ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3547ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3548ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3549ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3550ffd830a3SStefano Zampini         PetscInt j;
3551ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3552ffd830a3SStefano Zampini       }
3553ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3554ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3555ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
355606656605SStefano Zampini     }
355706656605SStefano Zampini 
3558ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3559ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3560ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3561ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3562ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
356306656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
356406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
356506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
356606656605SStefano Zampini     }
3567ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
35685b782168SStefano Zampini     if (B_C) {
3569ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3570ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3571ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3572ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3573ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3574ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3575ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
357606656605SStefano Zampini       }
3577ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
35785b782168SStefano Zampini     }
357906656605SStefano Zampini     /* coarse basis functions */
358006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
358106656605SStefano Zampini       PetscScalar *y;
358206656605SStefano Zampini 
3583ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
358406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
358506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
358606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
358706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
358806656605SStefano Zampini       if (i<n_vertices) {
358906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
359006656605SStefano Zampini       }
359106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
359206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
359306656605SStefano Zampini 
359406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
359506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
359606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
359706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
359806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
359906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
360006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
360106656605SStefano Zampini       }
360206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
360306656605SStefano Zampini     }
3604ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3605ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
360606656605SStefano Zampini   }
3607d62866d3SStefano Zampini   /* free memory */
360888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
360906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
361006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
361106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
361206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3613d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3614d62866d3SStefano Zampini   if (n_vertices) {
3615d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3616d62866d3SStefano Zampini   }
3617d62866d3SStefano Zampini   if (n_constraints) {
3618d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3619d62866d3SStefano Zampini   }
362088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
362188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
362288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3623d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
362488ebb749SStefano Zampini     Mat         coarse_sub_mat;
362525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
362688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
362788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
362888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
36298bec7fa6SStefano Zampini     Mat         C_B,CPHI;
36308bec7fa6SStefano Zampini     IS          is_dummy;
36318bec7fa6SStefano Zampini     Vec         mones;
363288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
363388ebb749SStefano Zampini     PetscReal   real_value;
363488ebb749SStefano Zampini 
3635a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3636a3df083aSStefano Zampini       Mat A;
3637a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3638a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3639a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3640a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3641a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3642a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3643a3df083aSStefano Zampini     } else {
364488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
364588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
364688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
364788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3648a3df083aSStefano Zampini     }
364988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
365088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3651ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
365288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
365388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
365488ebb749SStefano Zampini     }
365588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
365688ebb749SStefano Zampini 
365725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36583301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
365925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3660ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
366188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
366388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
366688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
366788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
366888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
366988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
367288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367388ebb749SStefano Zampini     } else {
367488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
367588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
367688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
367788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
367888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
367988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
368088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
368188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
368288ebb749SStefano Zampini     }
368388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
368588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3686511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
36874f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3688fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3689d12edf2fSStefano Zampini       PetscScalar *data,*data2;
36904f1b2e48SStefano Zampini       PetscInt    j;
3691d12edf2fSStefano Zampini 
36924f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3693fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3694d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
369586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3696d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3697d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
36984f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
36994f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3700d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
37014f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
37024f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
37034f1b2e48SStefano Zampini         }
3704d12edf2fSStefano Zampini       }
3705d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3706d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3707d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3708d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3709d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3710d12edf2fSStefano Zampini     }
3711d12edf2fSStefano Zampini #if 0
3712d12edf2fSStefano Zampini   {
3713d12edf2fSStefano Zampini     PetscViewer viewer;
3714d12edf2fSStefano Zampini     char filename[256];
3715ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3716d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3717d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3718ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3719ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3720ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3721d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
372272b8c272SStefano Zampini     if (save_change) {
372372b8c272SStefano Zampini       Mat phi_B;
372472b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
372572b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
372672b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
372772b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
372872b8c272SStefano Zampini     } else {
3729ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3730ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
373172b8c272SStefano Zampini     }
3732ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3733ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3734ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3735ffd830a3SStefano Zampini     }
3736ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3737ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3738ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3739ffd830a3SStefano Zampini     }
374072b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3741ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3742ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3743ffd830a3SStefano Zampini     }
3744d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3745d12edf2fSStefano Zampini   }
3746d12edf2fSStefano Zampini #endif
374781d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
37488bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
37491575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
375006656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
37518bec7fa6SStefano Zampini 
37528bec7fa6SStefano Zampini     /* check constraints */
3753a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3754a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
37554f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
37568bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3757a00504b5SStefano Zampini     } else {
3758a00504b5SStefano Zampini       PetscScalar *data;
3759a00504b5SStefano Zampini       Mat         tmat;
3760a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3761a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3762a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3763a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3764a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3765a00504b5SStefano Zampini     }
37668bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
37678bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
37688bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
37698bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3770bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3771ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3772bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3773bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3774bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3775bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3776bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
377788ebb749SStefano Zampini     }
37788bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
37798bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
37808bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37818bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
378225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
378388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
378488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
378588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
378688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
378788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
378888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
378988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
379088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
379188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
379288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3793ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
379488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
379588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
379688ebb749SStefano Zampini     }
379788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
379888ebb749SStefano Zampini   }
37998629588bSStefano Zampini   /* get back data */
38008629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
380188ebb749SStefano Zampini   PetscFunctionReturn(0);
380288ebb749SStefano Zampini }
380388ebb749SStefano Zampini 
380488ebb749SStefano Zampini #undef __FUNCT__
3805d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3806d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3807aa0d41d4SStefano Zampini {
3808d65f70fdSStefano Zampini   Mat            *work_mat;
3809d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3810d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3811c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3812aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3813aa0d41d4SStefano Zampini 
3814aa0d41d4SStefano Zampini   PetscFunctionBegin;
3815d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3816d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3817d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3818d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3819aa0d41d4SStefano Zampini 
3820d65f70fdSStefano Zampini   if (!rsorted) {
3821906d46d4SStefano Zampini     const PetscInt *idxs;
3822906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3823aa0d41d4SStefano Zampini 
3824d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3825d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3826d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3827d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3828aa0d41d4SStefano Zampini     }
3829d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3830d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3831d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3832d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3833aa0d41d4SStefano Zampini     }
3834d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3835d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3836d65f70fdSStefano Zampini   } else {
3837d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3838d65f70fdSStefano Zampini     isrow_s = isrow;
3839aa0d41d4SStefano Zampini   }
3840906d46d4SStefano Zampini 
3841d65f70fdSStefano Zampini   if (!csorted) {
3842d65f70fdSStefano Zampini     if (isrow == iscol) {
3843d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3844d65f70fdSStefano Zampini       iscol_s = isrow_s;
3845d65f70fdSStefano Zampini     } else {
3846d65f70fdSStefano Zampini       const PetscInt *idxs;
3847d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3848906d46d4SStefano Zampini 
3849d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3850d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3851d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3852d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3853d65f70fdSStefano Zampini       }
3854d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3855d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3856d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3857d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3858d65f70fdSStefano Zampini       }
3859d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3860d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3861d65f70fdSStefano Zampini     }
3862d65f70fdSStefano Zampini   } else {
3863d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3864d65f70fdSStefano Zampini     iscol_s = iscol;
3865d65f70fdSStefano Zampini   }
3866d65f70fdSStefano Zampini 
3867d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3868d65f70fdSStefano Zampini 
3869d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3870906d46d4SStefano Zampini     Mat      new_mat;
3871d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3872906d46d4SStefano Zampini 
3873d65f70fdSStefano Zampini     if (!rsorted) {
3874d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3875d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3876d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3877d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3878906d46d4SStefano Zampini       }
3879d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3880d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3881d65f70fdSStefano Zampini     } else {
3882d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3883906d46d4SStefano Zampini     }
3884d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3885d65f70fdSStefano Zampini 
3886d65f70fdSStefano Zampini     if (!csorted) {
3887d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3888d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3889d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3890d65f70fdSStefano Zampini       } else {
3891d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3892d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3893d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3894d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3895d65f70fdSStefano Zampini         }
3896d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3897d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3898d65f70fdSStefano Zampini       }
3899d65f70fdSStefano Zampini     } else {
3900d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3901d65f70fdSStefano Zampini     }
3902d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3903d65f70fdSStefano Zampini 
3904d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3905d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3906d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3907d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3908d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3909d65f70fdSStefano Zampini   }
3910d65f70fdSStefano Zampini 
3911d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3912d65f70fdSStefano Zampini   *B = work_mat[0];
3913d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3914d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3915d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3916d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3917d65f70fdSStefano Zampini }
3918d65f70fdSStefano Zampini 
3919d65f70fdSStefano Zampini #undef __FUNCT__
39205e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
39215e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3922aa0d41d4SStefano Zampini {
3923aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
39245e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3925d65f70fdSStefano Zampini   Mat            new_mat;
39265e8657edSStefano Zampini   IS             is_local,is_global;
3927d65f70fdSStefano Zampini   PetscInt       local_size;
3928d65f70fdSStefano Zampini   PetscBool      isseqaij;
3929aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3930aa0d41d4SStefano Zampini 
3931aa0d41d4SStefano Zampini   PetscFunctionBegin;
3932aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
39335e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
39345e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3935b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3936aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3937d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3938aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3939906d46d4SStefano Zampini 
3940906d46d4SStefano Zampini   /* check */
3941906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3942906d46d4SStefano Zampini     Vec       x,x_change;
3943906d46d4SStefano Zampini     PetscReal error;
3944906d46d4SStefano Zampini 
39455e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3946906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
39475e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3948e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3949e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3950d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3951e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3952e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3953906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3954906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3955906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3956906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3957906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3958906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3959906d46d4SStefano Zampini   }
3960906d46d4SStefano Zampini 
396122d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
39629b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
396322d5777bSStefano Zampini   if (isseqaij) {
3964a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3965a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3966aa0d41d4SStefano Zampini   } else {
3967a00504b5SStefano Zampini     Mat work_mat;
39681cf9b237SStefano Zampini 
3969a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3970aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3971a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
39721d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3973aa0d41d4SStefano Zampini   }
39743301b35fSStefano Zampini   if (matis->A->symmetric_set) {
39753301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3976e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39773301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3978e496cd5dSStefano Zampini #endif
39793301b35fSStefano Zampini   }
3980d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3981aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3982aa0d41d4SStefano Zampini }
3983aa0d41d4SStefano Zampini 
3984aa0d41d4SStefano Zampini #undef __FUNCT__
3985a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
39868ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3987a64d13efSStefano Zampini {
3988a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3989a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3990d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
399153892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
39923a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
39933a50541eSStefano Zampini   PetscInt        vbs,bs;
39946816873aSStefano Zampini   PetscBT         bitmask=NULL;
3995a64d13efSStefano Zampini   PetscErrorCode  ierr;
3996a64d13efSStefano Zampini 
3997a64d13efSStefano Zampini   PetscFunctionBegin;
3998b23d619eSStefano Zampini   /*
3999b23d619eSStefano Zampini     No need to setup local scatters if
4000b23d619eSStefano Zampini       - primal space is unchanged
4001b23d619eSStefano Zampini         AND
4002b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
4003b23d619eSStefano Zampini         AND
4004b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
4005b23d619eSStefano Zampini   */
4006b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
4007f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
4008f4ddd8eeSStefano Zampini   }
4009f4ddd8eeSStefano Zampini   /* destroy old objects */
4010f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
4011f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
4012f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
4013a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
4014b371cd4fSStefano Zampini   n_B = pcis->n_B;
4015b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
4016b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
40173a50541eSStefano Zampini 
4018a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
40196816873aSStefano Zampini 
402053892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
4021b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
4022854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
4023a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
4024a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
40250e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
4026a64d13efSStefano Zampini     }
4027a64d13efSStefano Zampini 
4028a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
40294641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
40306816873aSStefano Zampini         idx_R_local[n_R++] = i;
4031a64d13efSStefano Zampini       }
4032a64d13efSStefano Zampini     }
4033df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
4034df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
40356816873aSStefano Zampini 
4036df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4037df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
40386816873aSStefano Zampini   }
40393a50541eSStefano Zampini 
40403a50541eSStefano Zampini   /* Block code */
40413a50541eSStefano Zampini   vbs = 1;
40423a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
40433a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
40443a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
40453a50541eSStefano Zampini     PetscInt  *vary;
4046b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4047785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
40483a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4049d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4050d3df7717SStefano 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 */
40510e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4052d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
40533a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
40543a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
40553a50541eSStefano Zampini           break;
40563a50541eSStefano Zampini         }
40573a50541eSStefano Zampini       }
4058d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4059d3df7717SStefano Zampini     } else {
4060d3df7717SStefano Zampini       /* Verify directly the R set */
4061d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4062d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4063d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4064d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4065d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4066d3df7717SStefano Zampini             break;
4067d3df7717SStefano Zampini           }
4068d3df7717SStefano Zampini         }
4069d3df7717SStefano Zampini       }
4070d3df7717SStefano Zampini     }
40713a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
40723a50541eSStefano Zampini       vbs = bs;
40733a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
40743a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
40753a50541eSStefano Zampini       }
40763a50541eSStefano Zampini     }
40773a50541eSStefano Zampini   }
40783a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4079b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4080df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
408153892102SStefano Zampini 
4082df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4083df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
408453892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4085df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
408653892102SStefano Zampini   } else {
40873a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
408853892102SStefano Zampini   }
4089a64d13efSStefano Zampini 
4090a64d13efSStefano Zampini   /* print some info if requested */
4091a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4092a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4093a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40941575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4095a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4096a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
40974f1b2e48SStefano 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);
4098a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4099a64d13efSStefano Zampini   }
4100a64d13efSStefano Zampini 
4101a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4102b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
41036816873aSStefano Zampini     IS       is_aux1,is_aux2;
41046816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
41056816873aSStefano Zampini 
41063a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4107854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4108854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4109a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
41104641a718SStefano Zampini     for (i=0; i<n_D; i++) {
41114641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
41124641a718SStefano Zampini     }
4113a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4114a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
41154641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
41164641a718SStefano Zampini         aux_array1[j++] = i;
4117a64d13efSStefano Zampini       }
4118a64d13efSStefano Zampini     }
4119a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4120a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4121a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
41224641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
41234641a718SStefano Zampini         aux_array2[j++] = i;
4124a64d13efSStefano Zampini       }
4125a64d13efSStefano Zampini     }
4126a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4127a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4128a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4129a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4130a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4131a64d13efSStefano Zampini 
41328eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4133785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4134a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
41354641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
41364641a718SStefano Zampini           aux_array1[j++] = i;
4137a64d13efSStefano Zampini         }
4138a64d13efSStefano Zampini       }
4139a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4140a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4141a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4142a64d13efSStefano Zampini     }
41434641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
41443a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4145d62866d3SStefano Zampini   } else {
4146df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
41476816873aSStefano Zampini     IS                 tis;
41486816873aSStefano Zampini     PetscInt           schur_size;
41496816873aSStefano Zampini 
4150df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
41516816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4152df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
41536816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
41546816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41556816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
41566816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
41576816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4158d62866d3SStefano Zampini     }
4159d62866d3SStefano Zampini   }
4160a64d13efSStefano Zampini   PetscFunctionReturn(0);
4161a64d13efSStefano Zampini }
4162a64d13efSStefano Zampini 
4163304d26faSStefano Zampini 
4164304d26faSStefano Zampini #undef __FUNCT__
4165304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4166684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4167304d26faSStefano Zampini {
4168304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4169304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4170304d26faSStefano Zampini   PC             pc_temp;
4171304d26faSStefano Zampini   Mat            A_RR;
4172f4ddd8eeSStefano Zampini   MatReuse       reuse;
4173304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4174304d26faSStefano Zampini   PetscReal      value;
417504708bb6SStefano Zampini   PetscInt       n_D,n_R;
4176c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4177304d26faSStefano Zampini   PetscErrorCode ierr;
4178e604994aSStefano Zampini   /* prefixes stuff */
4179312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4180e604994aSStefano Zampini   size_t         len;
4181304d26faSStefano Zampini 
4182304d26faSStefano Zampini   PetscFunctionBegin;
4183304d26faSStefano Zampini 
4184e604994aSStefano Zampini   /* compute prefixes */
4185e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4186e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4187e604994aSStefano Zampini   if (!pcbddc->current_level) {
4188e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4189e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4190e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4191e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4192e604994aSStefano Zampini   } else {
4193e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4194312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4195e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4196e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4197312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4198312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
419934d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
420034d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4201e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4202e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4203e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4204e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4205e604994aSStefano Zampini   }
4206e604994aSStefano Zampini 
4207304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4208684f6988SStefano Zampini   if (dirichlet) {
4209d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4210450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
42119a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4212450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4213a3df083aSStefano Zampini         Mat    A_IIn;
4214a3df083aSStefano Zampini 
4215a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4216a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4217a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4218a3df083aSStefano Zampini       }
4219450f8f5eSStefano Zampini     }
42203301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
42213301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4222964fefecSStefano Zampini     }
4223ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4224964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4225304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4226304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4227304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4228304d26faSStefano Zampini       /* default */
4229304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4230e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
42319577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4232304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
42339577ea80SStefano Zampini       if (issbaij) {
42349577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
42359577ea80SStefano Zampini       } else {
4236304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
42379577ea80SStefano Zampini       }
4238304d26faSStefano Zampini       /* Allow user's customization */
4239304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4240304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4241304d26faSStefano Zampini     }
4242d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4243b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4244df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4245d62866d3SStefano Zampini 
4246df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4247d5574798SStefano Zampini     }
4248304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4249304d26faSStefano Zampini     if (!n_D) {
4250304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4251304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4252304d26faSStefano Zampini     }
4253304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4254304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4255304d26faSStefano Zampini     /* set ksp_D into pcis data */
4256304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4257304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4258304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4259684f6988SStefano Zampini   }
4260304d26faSStefano Zampini 
4261304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4262684f6988SStefano Zampini   A_RR = 0;
4263684f6988SStefano Zampini   if (neumann) {
4264d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
426504708bb6SStefano Zampini     PetscInt        ibs,mbs;
426604708bb6SStefano Zampini     PetscBool       issbaij;
426704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4268f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
42698ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4270f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4271f4ddd8eeSStefano Zampini       PetscInt nn_R;
427281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4273f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4274f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4275f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4276f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4277f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4278f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4279f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4280727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4281f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4282f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4283f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4284f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4285f4ddd8eeSStefano Zampini         }
4286f4ddd8eeSStefano Zampini       }
4287f4ddd8eeSStefano Zampini       /* last check */
4288d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4289f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4290f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4291f4ddd8eeSStefano Zampini       }
4292f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4293f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4294f4ddd8eeSStefano Zampini     }
4295a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4296af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4297af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
429804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
429904708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
430004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
430104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
430204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4303af732b37SStefano Zampini       } else {
4304511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
43056816873aSStefano Zampini       }
430604708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
430704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
430804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
430904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
431004708bb6SStefano Zampini       } else {
4311511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
431204708bb6SStefano Zampini       }
431304708bb6SStefano Zampini     }
4314a00504b5SStefano Zampini     /* extract A_RR */
4315b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4316a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4317a00504b5SStefano Zampini 
4318a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
431916e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4320a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
432116e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
432216e386b8SStefano Zampini         } else {
4323a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4324a00504b5SStefano Zampini         }
4325a00504b5SStefano Zampini       } else {
4326a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4327a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4328a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4329a00504b5SStefano Zampini       }
4330a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4331f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
433216e386b8SStefano Zampini     }
43333301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
43343301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
43356816873aSStefano Zampini     }
4336f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4337304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4338304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4339304d26faSStefano Zampini       /* default */
4340304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4341e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4342304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
43439577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
43449577ea80SStefano Zampini       if (issbaij) {
43459577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
43469577ea80SStefano Zampini       } else {
4347304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
43489577ea80SStefano Zampini       }
4349304d26faSStefano Zampini       /* Allow user's customization */
4350304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4351304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4352304d26faSStefano Zampini     }
4353304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4354304d26faSStefano Zampini     if (!n_R) {
4355304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4356304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4357304d26faSStefano Zampini     }
43585cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4359df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4360b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4361df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4362d62866d3SStefano Zampini 
4363df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4364d62866d3SStefano Zampini     }
4365304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4366304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4367684f6988SStefano Zampini   }
4368304d26faSStefano Zampini 
4369684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4370684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43711575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4372684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4373684f6988SStefano Zampini   }
4374c7017625SStefano Zampini 
4375c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4376c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4377c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4378c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4379c7017625SStefano Zampini   }
4380c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4381c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4382c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4383c7017625SStefano Zampini   }
4384c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4385c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4386c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4387c7017625SStefano Zampini   }
4388c7017625SStefano Zampini 
4389c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4390c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4391684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
43920fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
43930fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
43940fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
43950fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
43960fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4397e604994aSStefano 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);
4398c7017625SStefano Zampini       if (check_corr[0]) {
4399c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4400c7017625SStefano Zampini       }
4401304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4402304d26faSStefano Zampini     }
4403684f6988SStefano Zampini     if (neumann) { /* Neumann */
44040fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
44050fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
44060fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
44070fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
44080fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4409e604994aSStefano 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);
4410c7017625SStefano Zampini       if (check_corr[1]) {
4411c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4412c7017625SStefano Zampini       }
4413304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4414304d26faSStefano Zampini     }
4415684f6988SStefano Zampini   }
44165cbda25cSStefano Zampini   /* free Neumann problem's matrix */
44175cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4418304d26faSStefano Zampini   PetscFunctionReturn(0);
4419304d26faSStefano Zampini }
4420304d26faSStefano Zampini 
4421304d26faSStefano Zampini #undef __FUNCT__
4422ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
442380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4424674ae819SStefano Zampini {
4425674ae819SStefano Zampini   PetscErrorCode  ierr;
4426674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4427be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4428b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4429674ae819SStefano Zampini 
4430674ae819SStefano Zampini   PetscFunctionBegin;
4431b334f244SStefano Zampini   if (!reuse_solver) {
443280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
443320c7b377SStefano Zampini   }
443480677318SStefano Zampini   if (!pcbddc->switch_static) {
443580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
443680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
443780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
443820c7b377SStefano Zampini     }
4439b334f244SStefano Zampini     if (!reuse_solver) {
444080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
444220c7b377SStefano Zampini     } else {
4443df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4444be83ff47SStefano Zampini 
4445df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4446df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
444720c7b377SStefano Zampini     }
4448be83ff47SStefano Zampini   } else {
444980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
445480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
445580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
445680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
445780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4458674ae819SStefano Zampini     }
4459674ae819SStefano Zampini   }
4460b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
446180677318SStefano Zampini     if (applytranspose) {
446280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446380677318SStefano Zampini     } else {
446480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
446580677318SStefano Zampini     }
4466be83ff47SStefano Zampini   } else {
4467df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4468be83ff47SStefano Zampini 
4469be83ff47SStefano Zampini     if (applytranspose) {
4470df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4471be83ff47SStefano Zampini     } else {
4472df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4473be83ff47SStefano Zampini     }
4474be83ff47SStefano Zampini   }
447580677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
447680677318SStefano Zampini   if (!pcbddc->switch_static) {
4477b334f244SStefano Zampini     if (!reuse_solver) {
447880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
447980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4480be83ff47SStefano Zampini     } else {
4481df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4482be83ff47SStefano Zampini 
4483df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4484df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4485be83ff47SStefano Zampini     }
448680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
448780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
448880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
448980677318SStefano Zampini     }
449080677318SStefano Zampini   } else {
449180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
449580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
449680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
449780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
449880677318SStefano Zampini     }
449980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4503674ae819SStefano Zampini   }
4504674ae819SStefano Zampini   PetscFunctionReturn(0);
4505674ae819SStefano Zampini }
4506674ae819SStefano Zampini 
4507dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4508674ae819SStefano Zampini #undef __FUNCT__
4509674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4510dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4511674ae819SStefano Zampini {
4512674ae819SStefano Zampini   PetscErrorCode ierr;
4513674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4514674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4515674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4516674ae819SStefano Zampini 
4517674ae819SStefano Zampini   PetscFunctionBegin;
4518dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
45194fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4520dc359a40SStefano Zampini     if (applytranspose) {
4521674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
45228eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4523dc359a40SStefano Zampini     } else {
4524674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4525674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
452615aaf578SStefano Zampini     }
45274fee134fSStefano Zampini   } else {
45284fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
45294fee134fSStefano Zampini   }
4530efc2fbd9SStefano Zampini 
4531efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
45324f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4533efc2fbd9SStefano Zampini     PetscScalar *array;
45344f1b2e48SStefano Zampini     PetscInt    j;
4535efc2fbd9SStefano Zampini 
4536efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
45374f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4538efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4539efc2fbd9SStefano Zampini   }
4540efc2fbd9SStefano Zampini 
454112edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
454212edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
454312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
454512edc857SStefano Zampini 
45469f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
454712edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
454851694757SStefano Zampini     Mat          coarse_mat;
4549964fefecSStefano Zampini     Vec          rhs,sol;
455051694757SStefano Zampini     MatNullSpace nullsp;
455127b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4552964fefecSStefano Zampini 
455327b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
455427b6a85dSStefano Zampini       PC        coarse_pc;
455527b6a85dSStefano Zampini 
455627b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
455727b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
455827b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
455927b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
456027b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
456127b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
45623bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
456327b6a85dSStefano Zampini       }
456427b6a85dSStefano Zampini     }
4565964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4566964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
456751694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
456851694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
456951694757SStefano Zampini     if (nullsp) {
457051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
457151694757SStefano Zampini     }
457212edc857SStefano Zampini     if (applytranspose) {
45739a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4574964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
45752701bc32SStefano Zampini     } else {
45761f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
45772701bc32SStefano Zampini         PC        coarse_pc;
45782701bc32SStefano Zampini 
45792701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
45802701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
45813e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
45822701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
458312edc857SStefano Zampini       } else {
4584964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
458512edc857SStefano Zampini       }
45862701bc32SStefano Zampini     }
45871d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
458827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
458927b6a85dSStefano Zampini       PC        coarse_pc;
459027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
459127b6a85dSStefano Zampini 
459227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
459327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
459427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
45953bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
459627b6a85dSStefano Zampini     }
459751694757SStefano Zampini     if (nullsp) {
459851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
459951694757SStefano Zampini     }
460012edc857SStefano Zampini   }
4601674ae819SStefano Zampini 
4602674ae819SStefano Zampini   /* Local solution on R nodes */
46034fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
460480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
46059f00e9b4SStefano Zampini   }
46069f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
46079f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
460812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4609674ae819SStefano Zampini 
46104fee134fSStefano Zampini   /* Sum contributions from the two levels */
46114fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4612dc359a40SStefano Zampini     if (applytranspose) {
4613dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4614dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4615dc359a40SStefano Zampini     } else {
4616674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
46178eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4618dc359a40SStefano Zampini     }
4619efc2fbd9SStefano Zampini     /* store p0 */
46204f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4621efc2fbd9SStefano Zampini       PetscScalar *array;
46224f1b2e48SStefano Zampini       PetscInt    j;
4623efc2fbd9SStefano Zampini 
4624efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
46254f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4626efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4627efc2fbd9SStefano Zampini     }
46284fee134fSStefano Zampini   } else { /* expand the coarse solution */
46294fee134fSStefano Zampini     if (applytranspose) {
46304fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46314fee134fSStefano Zampini     } else {
46324fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
46334fee134fSStefano Zampini     }
46344fee134fSStefano Zampini   }
4635674ae819SStefano Zampini   PetscFunctionReturn(0);
4636674ae819SStefano Zampini }
4637674ae819SStefano Zampini 
4638674ae819SStefano Zampini #undef __FUNCT__
4639674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
464012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4641674ae819SStefano Zampini {
4642674ae819SStefano Zampini   PetscErrorCode ierr;
4643674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
464458da7f69SStefano Zampini   PetscScalar    *array;
464512edc857SStefano Zampini   Vec            from,to;
4646674ae819SStefano Zampini 
4647674ae819SStefano Zampini   PetscFunctionBegin;
464812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
464912edc857SStefano Zampini     from = pcbddc->coarse_vec;
465012edc857SStefano Zampini     to = pcbddc->vec1_P;
465112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
465212edc857SStefano Zampini       Vec tvec;
465358da7f69SStefano Zampini 
465458da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465558da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
465612edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465758da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
465858da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
465958da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
466012edc857SStefano Zampini     }
466112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
466212edc857SStefano Zampini     from = pcbddc->vec1_P;
466312edc857SStefano Zampini     to = pcbddc->coarse_vec;
466412edc857SStefano Zampini   }
466512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4666674ae819SStefano Zampini   PetscFunctionReturn(0);
4667674ae819SStefano Zampini }
4668674ae819SStefano Zampini 
4669674ae819SStefano Zampini #undef __FUNCT__
4670674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
467112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4672674ae819SStefano Zampini {
4673674ae819SStefano Zampini   PetscErrorCode ierr;
4674674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
467558da7f69SStefano Zampini   PetscScalar    *array;
467612edc857SStefano Zampini   Vec            from,to;
4677674ae819SStefano Zampini 
4678674ae819SStefano Zampini   PetscFunctionBegin;
467912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
468012edc857SStefano Zampini     from = pcbddc->coarse_vec;
468112edc857SStefano Zampini     to = pcbddc->vec1_P;
468212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
468312edc857SStefano Zampini     from = pcbddc->vec1_P;
468412edc857SStefano Zampini     to = pcbddc->coarse_vec;
468512edc857SStefano Zampini   }
468612edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
468712edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
468812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
468912edc857SStefano Zampini       Vec tvec;
469058da7f69SStefano Zampini 
469112edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
469258da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
469358da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
469458da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
469558da7f69SStefano Zampini     }
469658da7f69SStefano Zampini   } else {
469758da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
469858da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
469912edc857SStefano Zampini     }
470012edc857SStefano Zampini   }
4701674ae819SStefano Zampini   PetscFunctionReturn(0);
4702674ae819SStefano Zampini }
4703674ae819SStefano Zampini 
4704984c4197SStefano Zampini /* uncomment for testing purposes */
4705984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4706674ae819SStefano Zampini #undef __FUNCT__
4707674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4708674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4709674ae819SStefano Zampini {
4710674ae819SStefano Zampini   PetscErrorCode    ierr;
4711674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4712674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4713674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4714984c4197SStefano Zampini   /* one and zero */
4715984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4716984c4197SStefano Zampini   /* space to store constraints and their local indices */
47179162d606SStefano Zampini   PetscScalar       *constraints_data;
47189162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
47199162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
47209162d606SStefano Zampini   PetscInt          *constraints_n;
4721984c4197SStefano Zampini   /* iterators */
4722b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4723984c4197SStefano Zampini   /* BLAS integers */
4724e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4725e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4726c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4727727cdba6SStefano Zampini   /* reuse */
47280e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
47290e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4730984c4197SStefano Zampini   /* change of basis */
4731b3d85658SStefano Zampini   PetscBool         qr_needed;
47329162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4733984c4197SStefano Zampini   /* auxiliary stuff */
473464efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
47358a0068c3SStefano Zampini   PetscInt          ncc;
4736984c4197SStefano Zampini   /* some quantities */
473745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4738a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4739984c4197SStefano Zampini 
4740674ae819SStefano Zampini   PetscFunctionBegin;
47418e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
47428e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47438e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
474416909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4745088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4746088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
47470e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
47480e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
47490e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47500e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47510e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4752088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4753cf5a6209SStefano Zampini 
4754cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
47559162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4756cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4757cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4758cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4759cf5a6209SStefano Zampini     PetscScalar  *array;
4760cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4761cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4762674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4763b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4764674ae819SStefano Zampini     PetscScalar  *work;
4765674ae819SStefano Zampini     PetscReal    *singular_vals;
4766674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4767674ae819SStefano Zampini     PetscReal    *rwork;
4768674ae819SStefano Zampini #endif
4769674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4770674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4771674ae819SStefano Zampini #else
4772964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4773964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4774674ae819SStefano Zampini #endif
4775674ae819SStefano Zampini 
4776674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4777d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4778e4d548c7SStefano Zampini     /* print some info */
47791f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4780e4d548c7SStefano Zampini       PetscInt nv;
4781e4d548c7SStefano Zampini 
4782c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4783e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4784e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4785e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4786e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4787e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4788e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4789e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4790e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4791e4d548c7SStefano Zampini     }
4792e4d548c7SStefano Zampini 
4793d06fc5fdSStefano Zampini     /* free unneeded index sets */
4794d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4795d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4796674ae819SStefano Zampini     }
4797d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4798d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4799d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4800d06fc5fdSStefano Zampini       }
4801d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4802d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4803d06fc5fdSStefano Zampini     }
4804d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4805d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4806d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4807d06fc5fdSStefano Zampini       }
4808d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4809d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4810d06fc5fdSStefano Zampini     }
481170022509SStefano Zampini 
4812674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4813674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4814674ae819SStefano Zampini     if (nearnullsp) {
4815674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4816f4ddd8eeSStefano Zampini       /* remove any stored info */
4817f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4818f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4819f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4820f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4821f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4822473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4823f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4824f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4825f4ddd8eeSStefano Zampini       }
4826984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4827984c4197SStefano Zampini       nnsp_size = 0;
4828674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4829674ae819SStefano Zampini     }
4830984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4831984c4197SStefano Zampini     max_constraints = nnsp_size;
4832984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4833984c4197SStefano Zampini 
4834674ae819SStefano Zampini     /*
4835674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
48369162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
48379162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
48389162d606SStefano Zampini          There can be multiple constraints per connected component
4839674ae819SStefano Zampini                                                                                                                                                            */
4840674ae819SStefano Zampini     n_vertices = 0;
4841674ae819SStefano Zampini     if (ISForVertices) {
4842674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4843674ae819SStefano Zampini     }
48449162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
48459162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
48469162d606SStefano Zampini 
48479162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
48489162d606SStefano Zampini     total_counts *= max_constraints;
4849674ae819SStefano Zampini     total_counts += n_vertices;
48504641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
48519162d606SStefano Zampini 
4852674ae819SStefano Zampini     total_counts = 0;
4853674ae819SStefano Zampini     max_size_of_constraint = 0;
4854674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
48559162d606SStefano Zampini       IS used_is;
4856674ae819SStefano Zampini       if (i<n_ISForEdges) {
48579162d606SStefano Zampini         used_is = ISForEdges[i];
4858674ae819SStefano Zampini       } else {
48599162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4860674ae819SStefano Zampini       }
48619162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4862674ae819SStefano Zampini       total_counts += j;
4863674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4864674ae819SStefano Zampini     }
48659162d606SStefano 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);
48669162d606SStefano Zampini 
4867984c4197SStefano Zampini     /* get local part of global near null space vectors */
4868785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4869984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4870984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4871e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4872e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4873984c4197SStefano Zampini     }
4874674ae819SStefano Zampini 
4875242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4876242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4877a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4878242a89d7SStefano Zampini 
4879984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4880a773dcb8SStefano Zampini     if (!skip_lapack) {
4881674ae819SStefano Zampini       PetscScalar temp_work;
4882911cabfeSStefano Zampini 
4883674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4884984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4885785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4886785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4887785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4888674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4889785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4890674ae819SStefano Zampini #endif
4891674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4892c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4893c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4894674ae819SStefano Zampini       lwork = -1;
4895674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4896674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4897c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4898674ae819SStefano Zampini #else
4899c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4900674ae819SStefano Zampini #endif
4901674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4902984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4903674ae819SStefano Zampini #else /* on missing GESVD */
4904674ae819SStefano Zampini       /* SVD */
4905674ae819SStefano Zampini       PetscInt max_n,min_n;
4906674ae819SStefano Zampini       max_n = max_size_of_constraint;
4907984c4197SStefano Zampini       min_n = max_constraints;
4908984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4909674ae819SStefano Zampini         min_n = max_size_of_constraint;
4910984c4197SStefano Zampini         max_n = max_constraints;
4911674ae819SStefano Zampini       }
4912785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4913674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4914785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4915674ae819SStefano Zampini #endif
4916674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4917674ae819SStefano Zampini       lwork = -1;
4918e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4919e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4920b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4921674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4922674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
49239162d606SStefano 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));
4924674ae819SStefano Zampini #else
49259162d606SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr));
4926674ae819SStefano Zampini #endif
4927674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4928984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4929984c4197SStefano Zampini #endif /* on missing GESVD */
4930674ae819SStefano Zampini       /* Allocate optimal workspace */
4931674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4932854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4933674ae819SStefano Zampini     }
4934674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4935674ae819SStefano Zampini     total_counts = 0;
49369162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
49379162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4938674ae819SStefano Zampini     /* vertices */
49399162d606SStefano Zampini     if (n_vertices) {
4940674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
49419162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4942674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
49439162d606SStefano Zampini         constraints_n[total_counts] = 1;
49449162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
49459162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
49469162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4947674ae819SStefano Zampini         total_counts++;
4948674ae819SStefano Zampini       }
4949674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4950674ae819SStefano Zampini       n_vertices = total_counts;
4951674ae819SStefano Zampini     }
4952984c4197SStefano Zampini 
4953674ae819SStefano Zampini     /* edges and faces */
49549162d606SStefano Zampini     total_counts_cc = total_counts;
4955911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
49569162d606SStefano Zampini       IS        used_is;
49579162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
49589162d606SStefano Zampini 
4959911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
49609162d606SStefano Zampini         used_is = ISForEdges[ncc];
4961984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4962674ae819SStefano Zampini       } else {
49639162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4964984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4965674ae819SStefano Zampini       }
4966674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
49679162d606SStefano Zampini 
49689162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
49699162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4970984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4971984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4972674ae819SStefano Zampini       if (nnsp_has_cnst) {
49735b08dc53SStefano Zampini         PetscScalar quad_value;
49749162d606SStefano Zampini 
49759162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
49769162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
49779162d606SStefano Zampini 
4978a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4979674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4980a773dcb8SStefano Zampini         } else {
4981a773dcb8SStefano Zampini           quad_value = 1.0;
4982a773dcb8SStefano Zampini         }
4983674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49849162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4985674ae819SStefano Zampini         }
49869162d606SStefano Zampini         temp_constraints++;
4987674ae819SStefano Zampini         total_counts++;
4988674ae819SStefano Zampini       }
4989674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4990984c4197SStefano Zampini         PetscReal real_value;
49919162d606SStefano Zampini         PetscScalar *ptr_to_data;
49929162d606SStefano Zampini 
4993984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
49949162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4995674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49969162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4997674ae819SStefano Zampini         }
4998984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
4999984c4197SStefano Zampini         /* check if array is null on the connected component */
5000e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
50019162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
50025b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
5003674ae819SStefano Zampini           temp_constraints++;
5004674ae819SStefano Zampini           total_counts++;
50059162d606SStefano Zampini           if (!idxs_copied) {
50069162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
50079162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
5008674ae819SStefano Zampini           }
5009674ae819SStefano Zampini         }
50109162d606SStefano Zampini       }
50119162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
501245a1bb75SStefano Zampini       valid_constraints = temp_constraints;
5013eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
5014a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
50159162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
50169162d606SStefano Zampini 
50179162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5018a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
50199162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
5020a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
50219162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
5022a773dcb8SStefano Zampini         } else { /* perform SVD */
5023984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
50249162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
5025674ae819SStefano Zampini 
5026674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5027984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
5028984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
5029984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
5030984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
5031984c4197SStefano Zampini                 from that computed using LAPACKgesvd
5032984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
5033984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
5034984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
5035674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
5036e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5037984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5038674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
5039674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
50409162d606SStefano 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));
5041674ae819SStefano Zampini             }
5042674ae819SStefano Zampini           }
5043e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5044e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5045e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5046674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5047c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5048674ae819SStefano Zampini #else
5049c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5050674ae819SStefano Zampini #endif
5051674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5052984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5053984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5054674ae819SStefano Zampini           j = 0;
5055984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5056674ae819SStefano Zampini           total_counts = total_counts-j;
505745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5058e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5059c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5060c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5061c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5062c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5063c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5064c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5065674ae819SStefano Zampini           if (j<temp_constraints) {
5066984c4197SStefano Zampini             PetscInt ii;
5067984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5068674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50699162d606SStefano 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));
5070674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5071984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5072674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
50739162d606SStefano 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];
5074674ae819SStefano Zampini               }
5075674ae819SStefano Zampini             }
5076674ae819SStefano Zampini           }
5077674ae819SStefano Zampini #else  /* on missing GESVD */
5078e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5079e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5080b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5081674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5082674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
50839162d606SStefano 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));
5084674ae819SStefano Zampini #else
50859162d606SStefano Zampini           PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr));
5086674ae819SStefano Zampini #endif
5087984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5088674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5089984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5090e310c8b4SStefano Zampini           k = temp_constraints;
5091e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5092674ae819SStefano Zampini           j = 0;
5093e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
509445a1bb75SStefano Zampini           valid_constraints = k-j;
5095911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5096984c4197SStefano Zampini #endif /* on missing GESVD */
5097674ae819SStefano Zampini         }
5098a773dcb8SStefano Zampini       }
50999162d606SStefano Zampini       /* update pointers information */
51009162d606SStefano Zampini       if (valid_constraints) {
51019162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
51029162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
51039162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
51049162d606SStefano Zampini         /* set change_of_basis flag */
510545a1bb75SStefano Zampini         if (boolforchange) {
5106b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
51079162d606SStefano Zampini         }
5108b3d85658SStefano Zampini         total_counts_cc++;
510945a1bb75SStefano Zampini       }
511045a1bb75SStefano Zampini     }
5111984c4197SStefano Zampini     /* free workspace */
51128f1c130eSStefano Zampini     if (!skip_lapack) {
5113984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5114984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5115984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5116984c4197SStefano Zampini #endif
5117984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5118984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5119984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5120984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5121984c4197SStefano Zampini #endif
5122984c4197SStefano Zampini     }
5123984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5124984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5125984c4197SStefano Zampini     }
5126984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5127cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5128cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5129cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5130cf5a6209SStefano Zampini     }
5131cf5a6209SStefano Zampini     if (n_ISForFaces) {
5132cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5133cf5a6209SStefano Zampini     }
5134cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5135cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5136cf5a6209SStefano Zampini     }
5137cf5a6209SStefano Zampini     if (n_ISForEdges) {
5138cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5139cf5a6209SStefano Zampini     }
5140cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
514108122e43SStefano Zampini   } else {
514208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5143984c4197SStefano Zampini 
514408122e43SStefano Zampini     total_counts = 0;
514508122e43SStefano Zampini     n_vertices = 0;
5146d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5147d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
514808122e43SStefano Zampini     }
514908122e43SStefano Zampini     max_constraints = 0;
51509162d606SStefano Zampini     total_counts_cc = 0;
515108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
515208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
51539162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
515408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
515508122e43SStefano Zampini     }
51569162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
51579162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
51589162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
51599162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
516074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
51619162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
51629162d606SStefano Zampini     total_counts_cc = 0;
51639162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
51649162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
51659162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
516608122e43SStefano Zampini       }
516708122e43SStefano Zampini     }
51689162d606SStefano Zampini #if 0
51699162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
51709162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
51719162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
51729162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
51739162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
51749162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
51759162d606SStefano Zampini       }
51769162d606SStefano Zampini       printf("\n");
51779162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
51789162d606SStefano Zampini     }
51791b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
51808bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
51811b968477SStefano Zampini     }
51821b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
51838bec7fa6SStefano 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]);
51841b968477SStefano Zampini     }
518508122e43SStefano Zampini #endif
518608122e43SStefano Zampini 
51878bec7fa6SStefano Zampini     max_size_of_constraint = 0;
51889162d606SStefano 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]);
51899162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
519008122e43SStefano Zampini     /* Change of basis */
5191b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
519208122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
519308122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
519408122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5195b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
519608122e43SStefano Zampini         }
519708122e43SStefano Zampini       }
519808122e43SStefano Zampini     }
519908122e43SStefano Zampini   }
5200984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
52014f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
520208122e43SStefano Zampini 
52039162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
52049162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
52056c4ed002SBarry 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);
5206674ae819SStefano Zampini 
5207674ae819SStefano Zampini   /* Create constraint matrix */
5208674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
520916f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5210984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5211984c4197SStefano Zampini 
5212984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5213a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5214a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
521574d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5216984c4197SStefano Zampini   total_primal_vertices=0;
5217b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
52189162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
52199162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
522072b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
52219162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5222b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
522364efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
52249162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52259162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5226a717540cSStefano Zampini       }
5227b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
522891af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5229a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5230a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5231a717540cSStefano Zampini       }
5232fa434743SStefano Zampini     } else {
5233b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5234fa434743SStefano Zampini     }
5235a717540cSStefano Zampini   }
5236b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5237b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5238674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
523970022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5240b3d85658SStefano Zampini 
52414f1b2e48SStefano 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);
52420e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
52430e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5244984c4197SStefano Zampini 
5245984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
524674d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5247785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5248984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
524974d5cdf7SStefano Zampini 
5250984c4197SStefano Zampini   j = total_primal_vertices;
525174d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5252b3d85658SStefano Zampini   cum = total_primal_vertices;
52539162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52544641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5255b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5256b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5257b3d85658SStefano Zampini       cum++;
52589162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
525974d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
526074d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
526174d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
526274d5cdf7SStefano Zampini       }
52639162d606SStefano Zampini       j += constraints_n[i];
5264674ae819SStefano Zampini     }
5265674ae819SStefano Zampini   }
5266674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5267674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5268088faed8SStefano Zampini 
5269674ae819SStefano Zampini   /* set values in constraint matrix */
5270984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
52710e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5272674ae819SStefano Zampini   }
5273984c4197SStefano Zampini   total_counts = total_primal_vertices;
52749162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52754641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
52769162d606SStefano Zampini       PetscInt *cols;
52779162d606SStefano Zampini 
52789162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
52799162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
52809162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52819162d606SStefano Zampini         PetscInt    row = total_counts+k;
52829162d606SStefano Zampini         PetscScalar *vals;
52839162d606SStefano Zampini 
52849162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
52859162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
52869162d606SStefano Zampini       }
52879162d606SStefano Zampini       total_counts += constraints_n[i];
5288674ae819SStefano Zampini     }
5289674ae819SStefano Zampini   }
5290674ae819SStefano Zampini   /* assembling */
5291674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5292674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5293088faed8SStefano Zampini 
5294984c4197SStefano Zampini   /*
52956a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5296984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5297f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5298984c4197SStefano Zampini   */
5299674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5300674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5301026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5302984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5303984c4197SStefano Zampini     /* working stuff for GEQRF */
530481d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5305984c4197SStefano Zampini     PetscBLASInt lqr_work;
5306984c4197SStefano Zampini     /* working stuff for UNGQR */
5307984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5308984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5309984c4197SStefano Zampini     /* working stuff for TRTRS */
5310984c4197SStefano Zampini     PetscScalar  *trs_rhs;
53113f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5312984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5313984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5314984c4197SStefano Zampini     PetscScalar  *start_vals;
5315984c4197SStefano Zampini     /* working stuff for values insertion */
53164641a718SStefano Zampini     PetscBT      is_primal;
531764efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5318906d46d4SStefano Zampini     /* matrix sizes */
5319906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5320906d46d4SStefano Zampini     /* temporary change of basis */
5321906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5322cf5a6209SStefano Zampini     /* extra space for debugging */
5323cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5324984c4197SStefano Zampini 
5325906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5326906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
532716f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5328bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5329906d46d4SStefano Zampini     /* nonzeros for local mat */
5330bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
53311dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5332bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
53331dd7afcfSStefano Zampini     } else {
53341dd7afcfSStefano Zampini       const PetscInt *ii;
53351dd7afcfSStefano Zampini       PetscInt       n;
53361dd7afcfSStefano Zampini       PetscBool      flg_row;
53371dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53381dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
53391dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53401dd7afcfSStefano Zampini     }
53419162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5342a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
53439162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5344a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
53459162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5346a717540cSStefano Zampini         } else {
53479162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
53489162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5349a717540cSStefano Zampini         }
5350a717540cSStefano Zampini       }
5351a717540cSStefano Zampini     }
5352906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5353bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
53541dd7afcfSStefano Zampini     /* Set interior change in the matrix */
53551dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5356bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5357906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5358a717540cSStefano Zampini       }
53591dd7afcfSStefano Zampini     } else {
53601dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
53611dd7afcfSStefano Zampini       PetscScalar    *aa;
53621dd7afcfSStefano Zampini       PetscInt       n;
53631dd7afcfSStefano Zampini       PetscBool      flg_row;
53641dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53651dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53661dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
53671dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
53681dd7afcfSStefano Zampini       }
53691dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53701dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53711dd7afcfSStefano Zampini     }
5372a717540cSStefano Zampini 
5373a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5374a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5375a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5376a717540cSStefano Zampini     }
5377a717540cSStefano Zampini 
5378a717540cSStefano Zampini 
5379a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5380a717540cSStefano Zampini     /*
5381a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5382a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5383a717540cSStefano Zampini 
5384a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5385a717540cSStefano Zampini 
5386a6b551f4SStefano 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)
5387a6b551f4SStefano Zampini 
5388a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5389a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5390a717540cSStefano Zampini             |              ...                        |
5391a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5392a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5393a717540cSStefano Zampini 
5394a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5395a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5396a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5397a6b551f4SStefano Zampini 
5398a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5399a717540cSStefano Zampini     */
5400a717540cSStefano Zampini     if (qr_needed) {
5401984c4197SStefano Zampini       /* space to store Q */
5402854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
54034e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
54044e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5405984c4197SStefano Zampini       /* first we issue queries for optimal work */
54063f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54073f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
54083f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5409984c4197SStefano Zampini       lqr_work = -1;
54103f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5411984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5412984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5413785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5414984c4197SStefano Zampini       lgqr_work = -1;
54153f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
54163f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
54173f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
54183f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54193f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
54203f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5421984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5422984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5423785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5424984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5425785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5426a717540cSStefano Zampini       /* allocating workspace for check */
5427a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5428cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5429a717540cSStefano Zampini       }
5430a717540cSStefano Zampini     }
5431984c4197SStefano Zampini     /* array to store whether a node is primal or not */
54324641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5433473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
54340e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
54356c4ed002SBarry 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);
543639e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
543739e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
543839e2fb2aSStefano Zampini     }
543939e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5440984c4197SStefano Zampini 
5441a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
54429162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
54439162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
54444641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5445984c4197SStefano Zampini         /* get constraint info */
54469162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5447984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5448984c4197SStefano Zampini 
5449984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
54509162d606SStefano 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);
5451674ae819SStefano Zampini         }
5452984c4197SStefano Zampini 
5453fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5454a717540cSStefano Zampini 
5455a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5456a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
54579162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5458a717540cSStefano Zampini           }
5459984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
54609162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5461984c4197SStefano Zampini 
5462984c4197SStefano Zampini           /* compute QR decomposition of constraints */
54633f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54643f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54653f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5466674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54673f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5468984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5469674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5470984c4197SStefano Zampini 
5471984c4197SStefano Zampini           /* explictly compute R^-T */
5472984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5473984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
54743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54753f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
54763f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54773f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5478984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54793f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5480984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5481984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5482984c4197SStefano Zampini 
5483a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
54843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54853f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54863f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54873f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5488984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54893f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5490984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5491984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5492984c4197SStefano Zampini 
5493984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5494984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5495984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
54963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54983f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54993f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
55003f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
55013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5502984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
55039162d606SStefano 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));
5504984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
55059162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5506984c4197SStefano Zampini 
5507984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
55089162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5509984c4197SStefano Zampini           /* insert cols for primal dofs */
5510984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5511984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
55129162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5513906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5514984c4197SStefano Zampini           }
5515984c4197SStefano Zampini           /* insert cols for dual dofs */
5516984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
55179162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5518984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
55199162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5520906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5521984c4197SStefano Zampini               j++;
5522674ae819SStefano Zampini             }
5523674ae819SStefano Zampini           }
5524984c4197SStefano Zampini 
5525984c4197SStefano Zampini           /* check change of basis */
5526984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5527984c4197SStefano Zampini             PetscInt   ii,jj;
5528984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5529c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5530c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5531c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5532c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5533c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5534c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5535984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5536cf5a6209SStefano 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));
5537984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5538984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5539984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5540cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5541cf5a6209SStefano 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;
5542674ae819SStefano Zampini               }
5543674ae819SStefano Zampini             }
5544984c4197SStefano Zampini             if (!valid_qr) {
554522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5546984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5547984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5548cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5549cf5a6209SStefano 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]));
5550674ae819SStefano Zampini                   }
5551cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5552cf5a6209SStefano 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]));
5553984c4197SStefano Zampini                   }
5554984c4197SStefano Zampini                 }
5555984c4197SStefano Zampini               }
5556674ae819SStefano Zampini             } else {
555722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5558674ae819SStefano Zampini             }
5559674ae819SStefano Zampini           }
5560a717540cSStefano Zampini         } else { /* simple transformation block */
5561a717540cSStefano Zampini           PetscInt    row,col;
5562a6b551f4SStefano Zampini           PetscScalar val,norm;
5563a6b551f4SStefano Zampini 
5564a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55659162d606SStefano 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));
5566a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
55679162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
55689162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5569bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
55709162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5571906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
55729162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5573a717540cSStefano Zampini             } else {
5574a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
55759162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5576a717540cSStefano Zampini                 if (row != col) {
55779162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5578a717540cSStefano Zampini                 } else {
55799162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5580a717540cSStefano Zampini                 }
5581906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5582a717540cSStefano Zampini               }
5583a717540cSStefano Zampini             }
5584a717540cSStefano Zampini           }
558598a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
558622d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5587a717540cSStefano Zampini           }
5588674ae819SStefano Zampini         }
5589984c4197SStefano Zampini       } else {
5590984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
55919162d606SStefano 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);
5592674ae819SStefano Zampini         }
5593674ae819SStefano Zampini       }
5594674ae819SStefano Zampini     }
5595a717540cSStefano Zampini 
5596a717540cSStefano Zampini     /* free workspace */
5597a717540cSStefano Zampini     if (qr_needed) {
5598984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5599cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5600984c4197SStefano Zampini       }
5601984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5602984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5603984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5604984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5605984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5606674ae819SStefano Zampini     }
5607a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5608906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5609906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5610906d46d4SStefano Zampini 
5611906d46d4SStefano Zampini     /* assembling of global change of variable */
561288c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5613bbb9e6c6SStefano Zampini       Mat      tmat;
561416f15bc4SStefano Zampini       PetscInt bs;
561516f15bc4SStefano Zampini 
5616906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5617906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5618bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5619bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5620bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5621bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
562216f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
562316f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5624906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5625bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5626bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5627bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5628bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5629bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5630e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5631e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5632bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5633bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
563488c03ad3SStefano Zampini 
5635906d46d4SStefano Zampini       /* check */
5636906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5637906d46d4SStefano Zampini         PetscReal error;
5638906d46d4SStefano Zampini         Vec       x,x_change;
5639906d46d4SStefano Zampini 
5640906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5641906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5642906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5643906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5644e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5645e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5646bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5647e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5648e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5649906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5650906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5651906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5652906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5653bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5654906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5655906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5656906d46d4SStefano Zampini       }
5657b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5658b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5659b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5660bf3a8328SStefano Zampini 
56619a962809SStefano 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);
5662b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5663ac632422SStefano Zampini           Mat                    S_new,tmat;
5664bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5665bbb9e6c6SStefano Zampini 
5666bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
56676816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5668bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5669bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5670bf3a8328SStefano Zampini             IS                     is_V;
5671b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5672b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5673b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5674b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5675b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5676bf3a8328SStefano Zampini           }
5677bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5678ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5679b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5680ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5681bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5682bf3a8328SStefano Zampini             const PetscScalar *array;
5683bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5684bf3a8328SStefano Zampini             PetscInt          i,n_V;
5685bf3a8328SStefano Zampini 
5686b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5687b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5688b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5689b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5690b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5691b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5692b087196eSStefano Zampini               PetscScalar val;
5693b087196eSStefano Zampini               PetscInt    idx;
5694b087196eSStefano Zampini 
5695b087196eSStefano Zampini               idx = idxs_V[i];
5696b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5697b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5698b087196eSStefano Zampini             }
5699b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5700b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5701bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5702bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5703bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5704bf3a8328SStefano Zampini           }
5705ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5706ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5707ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5708ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5709b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5710ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5711bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5712b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5713bf3a8328SStefano Zampini             }
5714ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5715ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5716ac632422SStefano Zampini           }
5717b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
571888c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5719b96c3477SStefano Zampini         }
5720c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5721b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5722c9db6a07SStefano Zampini           PetscInt i;
5723c9db6a07SStefano Zampini 
5724c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5725c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5726c9db6a07SStefano Zampini           }
5727c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5728c9db6a07SStefano Zampini         }
5729b96c3477SStefano Zampini       }
573016909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
573116909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
573216909a7fSStefano Zampini       } else {
5733906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
573416909a7fSStefano Zampini       }
57351dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
573627b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
573772b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
573872b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
573972b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
574072b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
574172b8c272SStefano Zampini     }
57421dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
574327b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5744b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5745b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5746906d46d4SStefano Zampini     } else {
57471dd7afcfSStefano Zampini       Mat benign_global = NULL;
574827b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
57491dd7afcfSStefano Zampini         Mat tmat;
57501dd7afcfSStefano Zampini 
57511dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
57521dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
57531dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
57541dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57551dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57561dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
57571dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57581dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57591dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
57601dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
57611dd7afcfSStefano Zampini           Mat M;
57621dd7afcfSStefano Zampini 
57631dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
57641dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
57651dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
57661dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5767906d46d4SStefano Zampini         } else {
57681dd7afcfSStefano Zampini           Mat         eye;
57691dd7afcfSStefano Zampini           PetscScalar *array;
57701dd7afcfSStefano Zampini 
57711dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57721dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
57731dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
57741dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5775906d46d4SStefano Zampini           }
57761dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57771dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57781dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57791dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
57801dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
57811dd7afcfSStefano Zampini         }
57821dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
57831dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
57841dd7afcfSStefano Zampini       }
57851dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
57861dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57871dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
578827b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
57891dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
57901dd7afcfSStefano Zampini       }
57911dd7afcfSStefano Zampini     }
579216909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
579316909a7fSStefano Zampini       IS             is_global;
579416909a7fSStefano Zampini       const PetscInt *gidxs;
579516909a7fSStefano Zampini 
579616909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
579716909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
579816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
579916909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
580016909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
580116909a7fSStefano Zampini     }
58021dd7afcfSStefano Zampini   }
58031dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
58041dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5805b9b85e73SStefano Zampini   }
5806a717540cSStefano Zampini 
580772b8c272SStefano Zampini   if (!pcbddc->fake_change) {
58084f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
58094f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58104f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
58114f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5812019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5813019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5814019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5815019a44ceSStefano Zampini     }
5816019a44ceSStefano Zampini 
5817019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5818727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5819727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
58209f47a83aSStefano 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);
5821c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
58220e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
58239f47a83aSStefano 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);
5824727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5825727cdba6SStefano Zampini       }
58260e6343abSStefano Zampini     }
5827727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5828b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
582972b8c272SStefano Zampini   }
583072b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5831727cdba6SStefano Zampini 
5832a717540cSStefano Zampini   /* flush dbg viewer */
5833b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5834b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5835b8ffe317SStefano Zampini   }
5836a717540cSStefano Zampini 
5837e310c8b4SStefano Zampini   /* free workspace */
5838a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
58394641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
584008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
58419162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
58429162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
584308122e43SStefano Zampini   } else {
58449162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
58459162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
58469162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
584708122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
584808122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
58499162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
58509162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
585108122e43SStefano Zampini   }
5852674ae819SStefano Zampini   PetscFunctionReturn(0);
5853674ae819SStefano Zampini }
5854674ae819SStefano Zampini 
5855674ae819SStefano Zampini #undef __FUNCT__
5856674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5857674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5858674ae819SStefano Zampini {
585971582508SStefano Zampini   ISLocalToGlobalMapping map;
5860674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5861674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
586214f95afaSStefano Zampini   PetscInt               ierr,i,N;
5863674ae819SStefano Zampini 
5864674ae819SStefano Zampini   PetscFunctionBegin;
5865c8272957SStefano Zampini   if (pcbddc->graphanalyzed && !pcbddc->recompute_topography) PetscFunctionReturn(0);
58668e61c736SStefano Zampini   /* Reset previously computed graph */
58678e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5868674ae819SStefano Zampini   /* Init local Graph struct */
58697fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
587071582508SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5871be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5872674ae819SStefano Zampini 
5873575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
58749a962809SStefano 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);
58759577ea80SStefano Zampini 
5876674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5877d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
58784d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
58794d379d7bSStefano Zampini     PetscInt  nvtxs;
5880e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
5881674ae819SStefano Zampini 
58822fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
58832fffb893SStefano Zampini     if (flg_row) {
58844d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5885b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
58862fffb893SStefano Zampini     }
58872fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5888674ae819SStefano Zampini   }
58899b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
58909b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5891674ae819SStefano Zampini   }
5892674ae819SStefano Zampini 
5893674ae819SStefano Zampini   /* Setup of Graph */
58944b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
589514f95afaSStefano 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);
5896674ae819SStefano Zampini 
58974f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
58984f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
58994f1b2e48SStefano Zampini     PetscInt *local_subs;
59004f1b2e48SStefano Zampini 
59014f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
59024f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
59034f1b2e48SStefano Zampini       const PetscInt *idxs;
59044f1b2e48SStefano Zampini       PetscInt       nl,j;
59054f1b2e48SStefano Zampini 
59064f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
59074f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
590871582508SStefano Zampini       for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
59094f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
59104f1b2e48SStefano Zampini     }
59114f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
59124f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
59134f1b2e48SStefano Zampini   }
59144f1b2e48SStefano Zampini 
5915674ae819SStefano Zampini   /* Graph's connected components analysis */
5916674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
591771582508SStefano Zampini 
591871582508SStefano Zampini   /* set flag indicating analysis has been done */
591971582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_TRUE;
5920674ae819SStefano Zampini   PetscFunctionReturn(0);
5921674ae819SStefano Zampini }
5922674ae819SStefano Zampini 
59239a7d3425SStefano Zampini #undef __FUNCT__
59249a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
59259a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
59269a7d3425SStefano Zampini {
59279a7d3425SStefano Zampini   PetscInt       i,j;
59289a7d3425SStefano Zampini   PetscScalar    *alphas;
59299a7d3425SStefano Zampini   PetscErrorCode ierr;
59309a7d3425SStefano Zampini 
59319a7d3425SStefano Zampini   PetscFunctionBegin;
5932785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
59339a7d3425SStefano Zampini   for (i=0;i<n;i++) {
59349a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5935669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5936669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5937669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
59389a7d3425SStefano Zampini   }
59399a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
59409a7d3425SStefano Zampini   PetscFunctionReturn(0);
59419a7d3425SStefano Zampini }
59429a7d3425SStefano Zampini 
5943e7931f94SStefano Zampini #undef __FUNCT__
594470cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
594557de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5946e7931f94SStefano Zampini {
594757de7509SStefano Zampini   Mat            A;
5948e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5949e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
595052e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
595152e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
595227b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
595357de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
595427b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
595527b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
595627b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
595727b6a85dSStefano Zampini   MPI_Comm       subcomm;
595852e5ac9dSStefano Zampini   PetscErrorCode ierr;
5959a57a6d2fSStefano Zampini 
5960e7931f94SStefano Zampini   PetscFunctionBegin;
596157de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
596257de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
596357de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
596457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
596557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
596657de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
596757de7509SStefano Zampini 
596857de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
596957de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
597057de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
597157de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
597257de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
597357de7509SStefano Zampini   im_active = !!(n);
597457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
597557de7509SStefano Zampini   void_procs = size - active_procs;
597657de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
597757de7509SStefano Zampini   if (void_procs) {
597857de7509SStefano Zampini     PetscInt ncand;
597957de7509SStefano Zampini 
598057de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
598157de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
598257de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
598357de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
598457de7509SStefano Zampini       if (!procs_candidates[i]) {
598557de7509SStefano Zampini         procs_candidates[ncand++] = i;
598657de7509SStefano Zampini       }
598757de7509SStefano Zampini     }
598857de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
598957de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
599057de7509SStefano Zampini   }
599157de7509SStefano Zampini 
599214f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
599314f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
599414f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
599514f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
599614f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
599714f0bfb9SStefano Zampini     else dest = rank;
599857de7509SStefano Zampini     if (im_active) {
599957de7509SStefano Zampini       issize = 1;
600057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
600114f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
600257de7509SStefano Zampini       } else {
600314f0bfb9SStefano Zampini         isidx = dest;
600457de7509SStefano Zampini       }
600557de7509SStefano Zampini     } else {
600657de7509SStefano Zampini       issize = 0;
600757de7509SStefano Zampini       isidx = -1;
600857de7509SStefano Zampini     }
600957de7509SStefano Zampini     *n_subdomains = active_procs;
601057de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
6011daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
601257de7509SStefano Zampini     PetscFunctionReturn(0);
601357de7509SStefano Zampini   }
6014c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
6015c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
601627b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
6017e7931f94SStefano Zampini 
6018e7931f94SStefano Zampini   /* Get info on mapping */
60193bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
60203bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6021e7931f94SStefano Zampini 
6022e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
6023785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
6024e7931f94SStefano Zampini   xadj[0] = 0;
6025e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
6026785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
6027785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
602827b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
602927b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
603027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
603127b6a85dSStefano Zampini       count[shared[i][j]] += 1;
6032e7931f94SStefano Zampini 
603327b6a85dSStefano Zampini   xadj_count = 0;
60342b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
603527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
603627b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
6037d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
6038d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
6039d023bfaeSStefano Zampini         xadj_count++;
604027b6a85dSStefano Zampini         break;
604127b6a85dSStefano Zampini       }
6042e7931f94SStefano Zampini     }
6043e7931f94SStefano Zampini   }
6044d023bfaeSStefano Zampini   xadj[1] = xadj_count;
604527b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
60463bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6047e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6048e7931f94SStefano Zampini 
60493837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6050e7931f94SStefano Zampini 
605127b6a85dSStefano Zampini   /* Restrict work on active processes only */
605227b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
605327b6a85dSStefano Zampini   if (void_procs) {
605427b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
605527b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
605627b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
605727b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
605827b6a85dSStefano Zampini   } else {
605927b6a85dSStefano Zampini     psubcomm = NULL;
606027b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
606127b6a85dSStefano Zampini   }
606227b6a85dSStefano Zampini 
606327b6a85dSStefano Zampini   v_wgt = NULL;
606427b6a85dSStefano Zampini   if (!color) {
6065e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6066e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6067e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6068c8587f34SStefano Zampini   } else {
606952e5ac9dSStefano Zampini     Mat             subdomain_adj;
607052e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
607152e5ac9dSStefano Zampini     MatPartitioning partitioner;
607227b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
607352e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
607457de7509SStefano Zampini     PetscMPIInt     size;
6075b0c7d250SStefano Zampini     PetscBool       aggregate;
6076b0c7d250SStefano Zampini 
607727b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
607827b6a85dSStefano Zampini     if (void_procs) {
607927b6a85dSStefano Zampini       PetscInt prank = rank;
6080785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
608127b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6082e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6083e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6084c8587f34SStefano Zampini       }
6085e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
608627b6a85dSStefano Zampini     } else {
608727b6a85dSStefano Zampini       oldranks = NULL;
608827b6a85dSStefano Zampini     }
6089b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
609027b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6091b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6092b0c7d250SStefano Zampini       PetscMPIInt nrank;
6093b0c7d250SStefano Zampini       PetscScalar *vals;
6094b0c7d250SStefano Zampini 
609527b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6096b0c7d250SStefano Zampini       lrows = 0;
6097b0c7d250SStefano Zampini       if (nrank<redprocs) {
6098b0c7d250SStefano Zampini         lrows = size/redprocs;
6099b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6100b0c7d250SStefano Zampini       }
610127b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6102b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6103b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6104b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6105b0c7d250SStefano Zampini       row = nrank;
6106b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6107b0c7d250SStefano Zampini       cols = adjncy;
6108b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6109b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6110b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6111b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6112b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
611352e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
611452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
611552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6116b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
611727b6a85dSStefano Zampini       if (use_vwgt) {
611827b6a85dSStefano Zampini         Vec               v;
611927b6a85dSStefano Zampini         const PetscScalar *array;
612027b6a85dSStefano Zampini         PetscInt          nl;
612127b6a85dSStefano Zampini 
612227b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
612327b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
612427b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
612527b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
612627b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
612727b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
612827b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
612922db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
613027b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
613127b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
613227b6a85dSStefano Zampini       }
6133b0c7d250SStefano Zampini     } else {
613427b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
613527b6a85dSStefano Zampini       if (use_vwgt) {
613627b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
613727b6a85dSStefano Zampini         v_wgt[0] = local_size;
613827b6a85dSStefano Zampini       }
6139b0c7d250SStefano Zampini     }
614022b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6141e7931f94SStefano Zampini 
6142e7931f94SStefano Zampini     /* Partition */
614327b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6144e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
614527b6a85dSStefano Zampini     if (v_wgt) {
6146e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6147c8587f34SStefano Zampini     }
614857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
614957de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6150e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6151e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
615222b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6153e7931f94SStefano Zampini 
615452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
61556583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
615652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
615752e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
615857de7509SStefano Zampini     if (!aggregate) {
615957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
616027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
616127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
616227b6a85dSStefano Zampini #endif
616357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
616427b6a85dSStefano Zampini       } else if (oldranks) {
6165b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
616627b6a85dSStefano Zampini       } else {
616727b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
616857de7509SStefano Zampini       }
616928143c3dSStefano Zampini     } else {
6170b0c7d250SStefano Zampini       PetscInt    idxs[1];
6171b0c7d250SStefano Zampini       PetscMPIInt tag;
6172b0c7d250SStefano Zampini       MPI_Request *reqs;
6173b0c7d250SStefano Zampini 
6174b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6175b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6176b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
617727b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
617828143c3dSStefano Zampini       }
617927b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6180b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6181b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
618257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
618327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
618427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
618527b6a85dSStefano Zampini #endif
618657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
618727b6a85dSStefano Zampini       } else if (oldranks) {
6188b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
618927b6a85dSStefano Zampini       } else {
619027b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6191e7931f94SStefano Zampini       }
619257de7509SStefano Zampini     }
619352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6194e7931f94SStefano Zampini     /* clean up */
6195e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
619652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6197e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6198e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6199e7931f94SStefano Zampini   }
620027b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
620157de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6202e7931f94SStefano Zampini 
6203e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6204e7931f94SStefano Zampini   i = 1;
620527b6a85dSStefano Zampini   if (!color) i=0;
620657de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6207e7931f94SStefano Zampini   PetscFunctionReturn(0);
6208e7931f94SStefano Zampini }
6209e7931f94SStefano Zampini 
6210e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6211e7931f94SStefano Zampini 
6212e7931f94SStefano Zampini #undef __FUNCT__
6213e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
62141ae86dd6SStefano 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[])
6215e7931f94SStefano Zampini {
621670cf5478SStefano Zampini   Mat                    local_mat;
6217e7931f94SStefano Zampini   IS                     is_sends_internal;
62189d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
62191ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
62209d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6221e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6222e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6223e7931f94SStefano Zampini   const PetscInt*        is_indices;
6224e7931f94SStefano Zampini   MatType                new_local_type;
6225e7931f94SStefano Zampini   /* buffers */
6226e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
622728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
62289d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6229e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
62301ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6231e7931f94SStefano Zampini   /* MPI */
623228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
623328143c3dSStefano Zampini   PetscSubcomm           subcomm;
6234e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
623528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
623628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
62371ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
62381ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
62391ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6240e7931f94SStefano Zampini   PetscErrorCode         ierr;
6241e7931f94SStefano Zampini 
6242e7931f94SStefano Zampini   PetscFunctionBegin;
624357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6244e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
624528143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
624657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
624757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
624857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
624957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
625057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
62511ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
62521ae86dd6SStefano Zampini   if (nvecs) {
62531ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
62541ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
62551ae86dd6SStefano Zampini   }
625657de7509SStefano Zampini   /* further checks */
6257e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6258e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6259e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6260e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6261e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
626257de7509SStefano Zampini   if (reuse && *mat_n) {
626370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
626457de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
626570cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
626628143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
626770cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
626870cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
626970cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
627070cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
627170cf5478SStefano Zampini   }
6272e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6273e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
627457de7509SStefano Zampini 
6275e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6276e7931f94SStefano Zampini   if (!is_sends) {
627728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
627857de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6279c8587f34SStefano Zampini   } else {
6280e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6281e7931f94SStefano Zampini     is_sends_internal = is_sends;
6282c8587f34SStefano Zampini   }
6283e7931f94SStefano Zampini 
6284e7931f94SStefano Zampini   /* get comm */
6285a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6286e7931f94SStefano Zampini 
6287e7931f94SStefano Zampini   /* compute number of sends */
6288e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6289e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6290e7931f94SStefano Zampini 
6291e7931f94SStefano Zampini   /* compute number of receives */
6292e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6293785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6294e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6295e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6296e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6297e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6298e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6299e7931f94SStefano Zampini 
630028143c3dSStefano Zampini   /* restrict comm if requested */
630128143c3dSStefano Zampini   subcomm = 0;
630228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
630328143c3dSStefano Zampini   if (restrict_comm) {
6304779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6305779c1cceSStefano Zampini 
630628143c3dSStefano Zampini     color = 0;
630753a05cb3SStefano Zampini     if (restrict_full) {
630853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
630953a05cb3SStefano Zampini     } else {
631053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
631153a05cb3SStefano Zampini     }
6312b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
631328143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
631428143c3dSStefano Zampini     /* check if reuse has been requested */
631557de7509SStefano Zampini     if (reuse) {
631628143c3dSStefano Zampini       if (*mat_n) {
631728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
631828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
631928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
632028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
632128143c3dSStefano Zampini       } else {
632228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
632328143c3dSStefano Zampini       }
632428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6325779c1cceSStefano Zampini       PetscMPIInt rank;
6326779c1cceSStefano Zampini 
6327779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
632828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
632928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
633028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6331306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
633228143c3dSStefano Zampini     }
633328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
633428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
633528143c3dSStefano Zampini   } else {
633628143c3dSStefano Zampini     comm_n = comm;
633728143c3dSStefano Zampini   }
633828143c3dSStefano Zampini 
6339e7931f94SStefano Zampini   /* prepare send/receive buffers */
6340785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6341e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6342785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6343e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
634428143c3dSStefano Zampini   if (nis) {
6345854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
634628143c3dSStefano Zampini   }
6347e7931f94SStefano Zampini 
634828143c3dSStefano Zampini   /* Get data from local matrices */
63496c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6350e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6351e7931f94SStefano Zampini     /*
6352e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6353e7931f94SStefano Zampini        send_buffer_idxs should contain:
6354e7931f94SStefano Zampini        - MatType_PRIVATE type
6355e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6356e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6357e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6358e7931f94SStefano Zampini     */
63596c4ed002SBarry Smith   else {
6360e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
63613bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6362854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6363e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6364e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
63653bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6366e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
63673bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6368e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6369e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6370e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6371e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6372c8587f34SStefano Zampini     }
6373c8587f34SStefano Zampini   }
6374e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
637528143c3dSStefano Zampini   /* additional is (if any) */
637628143c3dSStefano Zampini   if (nis) {
637728143c3dSStefano Zampini     PetscMPIInt psum;
637828143c3dSStefano Zampini     PetscInt j;
637928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
638028143c3dSStefano Zampini       PetscInt plen;
638128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
638228143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
638328143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
638428143c3dSStefano Zampini     }
6385854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
638628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
638728143c3dSStefano Zampini       PetscInt plen;
638828143c3dSStefano Zampini       const PetscInt *is_array_idxs;
638928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
639028143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
639128143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
639228143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
639328143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
639428143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
639528143c3dSStefano Zampini     }
639628143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
639728143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
639828143c3dSStefano Zampini     }
639928143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
640028143c3dSStefano Zampini   }
640128143c3dSStefano Zampini 
6402e7931f94SStefano Zampini   buf_size_idxs = 0;
6403e7931f94SStefano Zampini   buf_size_vals = 0;
640428143c3dSStefano Zampini   buf_size_idxs_is = 0;
64051ae86dd6SStefano Zampini   buf_size_vecs = 0;
6406e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6407e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6408e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
640928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
64101ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6411e7931f94SStefano Zampini   }
6412785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6413785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
641495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
64151ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6416e7931f94SStefano Zampini 
6417e7931f94SStefano Zampini   /* get new tags for clean communications */
6418e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6419e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
642028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
64211ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6422e7931f94SStefano Zampini 
6423e7931f94SStefano Zampini   /* allocate for requests */
6424785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6425785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
642695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
64271ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6428785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6429785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
643095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
64311ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6432e7931f94SStefano Zampini 
6433e7931f94SStefano Zampini   /* communications */
6434e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6435e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
643628143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
64371ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6438e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6439e7931f94SStefano Zampini     source_dest = onodes[i];
6440e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6441e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6442e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6443e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
644428143c3dSStefano Zampini     if (nis) {
644557de7509SStefano Zampini       source_dest = onodes_is[i];
644628143c3dSStefano 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);
644728143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
644828143c3dSStefano Zampini     }
64491ae86dd6SStefano Zampini     if (nvecs) {
64501ae86dd6SStefano Zampini       source_dest = onodes[i];
64511ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
64521ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
64531ae86dd6SStefano Zampini     }
6454e7931f94SStefano Zampini   }
6455e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6456e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6457e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6458e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
645928143c3dSStefano Zampini     if (nis) {
646028143c3dSStefano 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);
646128143c3dSStefano Zampini     }
64621ae86dd6SStefano Zampini     if (nvecs) {
64631ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64641ae86dd6SStefano 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);
64651ae86dd6SStefano Zampini     }
6466e7931f94SStefano Zampini   }
6467e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6468e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6469e7931f94SStefano Zampini 
6470e7931f94SStefano Zampini   /* assemble new l2g map */
6471e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6472e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64739d30be91SStefano Zampini   new_local_rows = 0;
6474e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64759d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6476e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6477e7931f94SStefano Zampini   }
64789d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6479e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64809d30be91SStefano Zampini   new_local_rows = 0;
6481e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64829d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
64839d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6484e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6485e7931f94SStefano Zampini   }
64869d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
64879d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6488e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6489e7931f94SStefano Zampini 
6490e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6491e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6492e7931f94SStefano 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) */
6493e7931f94SStefano Zampini   if (n_recvs) {
649428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6495e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6496e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6497e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6498e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6499e7931f94SStefano Zampini         break;
6500e7931f94SStefano Zampini       }
6501e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6502e7931f94SStefano Zampini     }
6503e7931f94SStefano Zampini     switch (new_local_type_private) {
650428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
650528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6506e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6507e7931f94SStefano Zampini           bs = 1;
650828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
650928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
651028143c3dSStefano Zampini           bs = 1;
651128143c3dSStefano Zampini         }
6512e7931f94SStefano Zampini         break;
6513e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6514e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6515e7931f94SStefano Zampini         bs = 1;
6516e7931f94SStefano Zampini         break;
6517e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6518e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6519e7931f94SStefano Zampini         break;
6520e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6521e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6522e7931f94SStefano Zampini         break;
6523e7931f94SStefano Zampini       default:
65249d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6525e7931f94SStefano Zampini         break;
6526e7931f94SStefano Zampini     }
652728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
652828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
652928143c3dSStefano Zampini     bs = 1;
6530e7931f94SStefano Zampini   }
6531e7931f94SStefano Zampini 
653270cf5478SStefano Zampini   /* create MATIS object if needed */
653357de7509SStefano Zampini   if (!reuse) {
6534e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6535e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
653670cf5478SStefano Zampini   } else {
653770cf5478SStefano Zampini     /* it also destroys the local matrices */
653857de7509SStefano Zampini     if (*mat_n) {
653970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
654057de7509SStefano Zampini     } else { /* this is a fake object */
654157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
654257de7509SStefano Zampini     }
654370cf5478SStefano Zampini   }
654470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6545e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
65469d30be91SStefano Zampini 
65479d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
65489d30be91SStefano Zampini 
65499d30be91SStefano Zampini   /* Global to local map of received indices */
65509d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
65519d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
65529d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
65539d30be91SStefano Zampini 
65549d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
65559d30be91SStefano Zampini   buf_size_idxs = 0;
65569d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
65579d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
65589d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
65599d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
65609d30be91SStefano Zampini   }
65619d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
65629d30be91SStefano Zampini 
65639d30be91SStefano Zampini   /* set preallocation */
65649d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
65659d30be91SStefano Zampini   if (!newisdense) {
65669d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
65679d30be91SStefano Zampini 
65689d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
65699d30be91SStefano Zampini     if (n_recvs) {
65709d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
65719d30be91SStefano Zampini     }
65729d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
65739d30be91SStefano Zampini       PetscInt j;
65749d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
65759d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
65769d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
65779d30be91SStefano Zampini         }
65789d30be91SStefano Zampini       } else {
65799d30be91SStefano Zampini         /* TODO */
65809d30be91SStefano Zampini       }
65819d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
65829d30be91SStefano Zampini     }
65839d30be91SStefano Zampini     if (new_local_nnz) {
65849d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
65859d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
65869d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
65879d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65889d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
65899d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65909d30be91SStefano Zampini     } else {
65919d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65929d30be91SStefano Zampini     }
65939d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
65949d30be91SStefano Zampini   } else {
65959d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65969d30be91SStefano Zampini   }
6597e7931f94SStefano Zampini 
6598e7931f94SStefano Zampini   /* set values */
6599e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
66009d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6601e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6602e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6603e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
66049d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6605e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6606e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6607e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
660828143c3dSStefano Zampini     } else {
660928143c3dSStefano Zampini       /* TODO */
6610e7931f94SStefano Zampini     }
6611e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6612e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6613e7931f94SStefano Zampini   }
6614e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6615e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
661670cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
661770cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66189d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6619e7931f94SStefano Zampini 
6620dfd14d43SStefano Zampini #if 0
662128143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6622e7931f94SStefano Zampini     Vec       lvec,rvec;
6623e7931f94SStefano Zampini     PetscReal infty_error;
6624e7931f94SStefano Zampini 
66252a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6626e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6627e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6628e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
662970cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6630e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6631e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6632e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6633e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6634e7931f94SStefano Zampini   }
663528143c3dSStefano Zampini #endif
6636e7931f94SStefano Zampini 
663728143c3dSStefano Zampini   /* assemble new additional is (if any) */
663828143c3dSStefano Zampini   if (nis) {
663928143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
664028143c3dSStefano Zampini 
664128143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6642854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
664328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
664428143c3dSStefano Zampini     psum = 0;
664528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
664628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
664728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
664828143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
664928143c3dSStefano Zampini         psum += plen;
665028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
665128143c3dSStefano Zampini       }
665228143c3dSStefano Zampini     }
6653854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6654854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
665528143c3dSStefano Zampini     for (i=1;i<nis;i++) {
665628143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
665728143c3dSStefano Zampini     }
665828143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
665928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
666028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
666128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
666228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
666328143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
666428143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
666528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
666628143c3dSStefano Zampini       }
666728143c3dSStefano Zampini     }
666828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
666928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
667028143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
667128143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
667228143c3dSStefano Zampini     }
667328143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
667428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
667528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
667628143c3dSStefano Zampini   }
6677e7931f94SStefano Zampini   /* free workspace */
667828143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6679e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6680e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6681e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6682e7931f94SStefano Zampini   if (isdense) {
6683e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6684e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6685e7931f94SStefano Zampini   } else {
6686e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6687e7931f94SStefano Zampini   }
668828143c3dSStefano Zampini   if (nis) {
668928143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
669028143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
669128143c3dSStefano Zampini   }
66921ae86dd6SStefano Zampini 
66931ae86dd6SStefano Zampini   if (nvecs) {
66941ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66951ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66961ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
66971ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
66981ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
66991ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
67001ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
67011ae86dd6SStefano Zampini     /* set values */
67021ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
67031ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
67041ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67051ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
67061ae86dd6SStefano Zampini       PetscInt j;
67071ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
67081ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
67091ae86dd6SStefano Zampini       }
67101ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
67111ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
67121ae86dd6SStefano Zampini     }
67131ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
67141ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
67151ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
67161ae86dd6SStefano Zampini   }
67171ae86dd6SStefano Zampini 
67181ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
67191ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6720e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6721e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
67221ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
672328143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6724e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6725e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
67261ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
672728143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6728e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6729e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6730e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6731e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6732e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
673328143c3dSStefano Zampini   if (nis) {
673428143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
673528143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
673628143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
673728143c3dSStefano Zampini   }
673828143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
673928143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
674028143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
674128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
674228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
674328143c3dSStefano Zampini     }
67441ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
67451ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
67461ae86dd6SStefano Zampini     }
674753a05cb3SStefano Zampini     *mat_n = NULL;
674828143c3dSStefano Zampini   }
6749e7931f94SStefano Zampini   PetscFunctionReturn(0);
6750e7931f94SStefano Zampini }
6751a57a6d2fSStefano Zampini 
675212edc857SStefano Zampini /* temporary hack into ksp private data structure */
6753af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
675412edc857SStefano Zampini 
6755c8587f34SStefano Zampini #undef __FUNCT__
6756c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6757c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6758c8587f34SStefano Zampini {
6759c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6760c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
676120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
67621ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
67639881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
676420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
67656e683305SStefano Zampini   IS                     coarse_is,*isarray;
67666e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
676730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6768f9eb5b7dSStefano Zampini   PC                     pc_temp;
6769c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6770c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6771f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
67724f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
67736e683305SStefano Zampini   Mat                    t_coarse_mat_is;
677457de7509SStefano Zampini   PetscInt               ncoarse;
677568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
677622bc73bbSStefano Zampini   PetscScalar            *array;
677757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
677857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
67799881197aSStefano Zampini   PetscErrorCode         ierr;
6780fdc09c96SStefano Zampini 
6781c8587f34SStefano Zampini   PetscFunctionBegin;
6782c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
678368457ee5SStefano 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 */
6784fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
67855a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6786fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6787f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6788f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6789f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6790fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
679151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
679251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6793dc4bcba2SStefano Zampini         PC        pc;
6794dc4bcba2SStefano Zampini         PetscBool isbddc;
6795dc4bcba2SStefano Zampini 
6796dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6797dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6798dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6799dc4bcba2SStefano Zampini         if (isbddc) {
680063c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
680163c961adSStefano Zampini         } else {
6802727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
680363c961adSStefano Zampini         }
6804fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6805fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6806fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6807f4ddd8eeSStefano Zampini       }
6808fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6809fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6810f4ddd8eeSStefano Zampini     }
681170cf5478SStefano Zampini     /* reset any subassembling information */
681257de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
681370cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
681457de7509SStefano Zampini     }
68156e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6816fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6817f4ddd8eeSStefano Zampini   }
681857de7509SStefano Zampini   /* assemble coarse matrix */
681957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
682057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
682157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
682257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
682318a45a71SStefano Zampini   } else {
682457de7509SStefano Zampini     coarse_mat = NULL;
682557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
68266e683305SStefano Zampini   }
6827e7931f94SStefano Zampini 
6828abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6829abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6830abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6831abbbba34SStefano Zampini 
6832abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
683322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
683422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
683522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
683622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6837e176bc59SStefano 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);
68386e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
68396e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68406e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6841abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6842abbbba34SStefano Zampini 
684357de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
684457de7509SStefano Zampini   im_active = !!(pcis->n);
684557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
684657de7509SStefano Zampini 
684714f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
684857de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
684957de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
685057de7509SStefano Zampini   coarse_mat_is = NULL;
685157de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
685257de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
685357de7509SStefano Zampini   full_restr = PETSC_TRUE;
68541ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
685557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
685657de7509SStefano Zampini   if (multilevel_requested) {
685757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
685857de7509SStefano Zampini     restr = PETSC_FALSE;
685957de7509SStefano Zampini     full_restr = PETSC_FALSE;
686057de7509SStefano Zampini   } else {
686157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
686257de7509SStefano Zampini     restr = PETSC_TRUE;
686357de7509SStefano Zampini     full_restr = PETSC_TRUE;
686457de7509SStefano Zampini   }
68654b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
686657de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
686757de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6868a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
686957de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6870a198735bSStefano Zampini     } else {
6871a198735bSStefano Zampini       PetscMPIInt size,rank;
6872a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6873a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6874a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6875a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6876a198735bSStefano Zampini     }
687757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
687857de7509SStefano Zampini     PetscInt    psum;
687957de7509SStefano Zampini     PetscMPIInt size;
688057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
688157de7509SStefano Zampini     else psum = 0;
688257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
688357de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
688457de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
688557de7509SStefano Zampini   }
688657de7509SStefano Zampini   /* determine if we can go multilevel */
688757de7509SStefano Zampini   if (multilevel_requested) {
688857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
688957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
689057de7509SStefano Zampini   }
689157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
689257de7509SStefano Zampini 
6893e4d548c7SStefano Zampini   /* dump subassembling pattern */
6894e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6895e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6896e4d548c7SStefano Zampini   }
6897e4d548c7SStefano Zampini 
68986e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
689927b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
69006e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
69016e683305SStefano Zampini     const PetscInt         *idxs;
69026e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
69036e683305SStefano Zampini 
69046e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
69050be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
69066e683305SStefano Zampini     /* allocate space for temporary storage */
6907854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6908854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
69096e683305SStefano Zampini     /* allocate for IS array */
69106e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
69116e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
691227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
691330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6914854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
69156e683305SStefano Zampini     /* dofs splitting */
69166e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
69176e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
69186e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
69196e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69206e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69216e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
69226e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
692330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
69246e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
69256e683305SStefano Zampini     }
69266e683305SStefano Zampini     /* neumann boundaries */
69276e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
69286e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
69296e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
69306e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69316e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
69326e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
69336e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
693430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
69356e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
69366e683305SStefano Zampini     }
69376e683305SStefano Zampini     /* free memory */
69386e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
69396e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
69406e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
69416e683305SStefano Zampini   } else {
69426e683305SStefano Zampini     nis = 0;
69436e683305SStefano Zampini     nisdofs = 0;
69446e683305SStefano Zampini     nisneu = 0;
694530368db7SStefano Zampini     nisvert = 0;
69466e683305SStefano Zampini     isarray = NULL;
69476e683305SStefano Zampini   }
69486e683305SStefano Zampini   /* destroy no longer needed map */
69496e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
69506e683305SStefano Zampini 
695157de7509SStefano Zampini   /* subassemble */
695257de7509SStefano Zampini   if (multilevel_allowed) {
69531ae86dd6SStefano Zampini     Vec       vp[1];
69541ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
695557de7509SStefano Zampini     PetscBool reuse,reuser;
69561ae86dd6SStefano Zampini 
695757de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
695857de7509SStefano Zampini     else reuse = PETSC_FALSE;
695957de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
69601ae86dd6SStefano Zampini     vp[0] = NULL;
69611ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
69621ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
69631ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
69641ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
69651ae86dd6SStefano Zampini       nvecs = 1;
69661ae86dd6SStefano Zampini 
69671ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6968a198735bSStefano Zampini         Mat      B,loc_divudotp;
69691ae86dd6SStefano Zampini         Vec      v,p;
69701ae86dd6SStefano Zampini         IS       dummy;
69711ae86dd6SStefano Zampini         PetscInt np;
69721ae86dd6SStefano Zampini 
6973a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6974a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
69751ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6976a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
69771ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
69781ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
69791ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
69801ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
69811ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
69821ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
69831ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
69841ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
69851ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
69861ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
69871ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
69881ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
698974e2c79eSStefano Zampini       }
69901ae86dd6SStefano Zampini     }
69911ae86dd6SStefano Zampini     if (reuser) {
69921ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
699374e2c79eSStefano Zampini     } else {
69941ae86dd6SStefano 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);
69951ae86dd6SStefano Zampini     }
69961ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
69971ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
69981ae86dd6SStefano Zampini       PetscInt    nl;
69991ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
70001ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
70011ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
70021ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
70031ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
70041ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
70051ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
70061ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
7007a198735bSStefano Zampini     } else {
7008a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
70091ae86dd6SStefano Zampini     }
70101ae86dd6SStefano Zampini   } else {
70111ae86dd6SStefano 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);
70126e683305SStefano Zampini   }
701357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
701457de7509SStefano Zampini     PetscMPIInt size;
701557de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
701657de7509SStefano Zampini     if (!multilevel_allowed) {
701757de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
70186e683305SStefano Zampini     } else {
701957de7509SStefano Zampini       Mat A;
7020779c1cceSStefano Zampini 
702157de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
702257de7509SStefano Zampini       if (coarse_mat_is) {
702357de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
702457de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
702557de7509SStefano Zampini         coarse_mat = coarse_mat_is;
702657de7509SStefano Zampini       }
702757de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
702857de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
702957de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
7030779c1cceSStefano Zampini     }
7031779c1cceSStefano Zampini   }
703257de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
703357de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
70346e683305SStefano Zampini 
70356e683305SStefano Zampini   /* create local to global scatters for coarse problem */
703668457ee5SStefano Zampini   if (compute_vecs) {
70376e683305SStefano Zampini     PetscInt lrows;
70386e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
703957de7509SStefano Zampini     if (coarse_mat) {
704057de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
70416e683305SStefano Zampini     } else {
70426e683305SStefano Zampini       lrows = 0;
70436e683305SStefano Zampini     }
70446e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
70456e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
70466e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
70476e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70486e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70496e683305SStefano Zampini   }
70506e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7051c8587f34SStefano Zampini 
7052f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7053f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7054f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7055f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7056f9eb5b7dSStefano Zampini   } else {
7057f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7058f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7059c8587f34SStefano Zampini   }
7060c8587f34SStefano Zampini 
70616e683305SStefano Zampini   /* print some info if requested */
70626e683305SStefano Zampini   if (pcbddc->dbg_flag) {
70636e683305SStefano Zampini     if (!multilevel_allowed) {
70646e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
70656e683305SStefano Zampini       if (multilevel_requested) {
70666e683305SStefano 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);
70676e683305SStefano Zampini       } else if (pcbddc->max_levels) {
70686e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
70696e683305SStefano Zampini       }
70706e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
70716e683305SStefano Zampini     }
70726e683305SStefano Zampini   }
70736e683305SStefano Zampini 
7074f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
707557de7509SStefano Zampini   if (coarse_mat) {
70766a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
70776e683305SStefano Zampini     if (pcbddc->dbg_flag) {
707857de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
70796e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
70806e683305SStefano Zampini     }
7081f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7082312be037SStefano Zampini       char prefix[256],str_level[16];
7083e604994aSStefano Zampini       size_t len;
708457de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7085422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7086c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7087f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
708857de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7089c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
70906e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7091c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
7092c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7093e604994aSStefano Zampini       /* prefix */
7094e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7095e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7096e604994aSStefano Zampini       if (!pcbddc->current_level) {
7097e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7098e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7099c8587f34SStefano Zampini       } else {
7100e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7101312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7102312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
710334d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7104312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7105e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7106e604994aSStefano Zampini       }
7107e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
71083e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
71093e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
71103e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
71113e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7112f9eb5b7dSStefano Zampini       /* allow user customization */
7113f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
71143e3c6dadSStefano Zampini     }
71153e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
711651bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
71173e3c6dadSStefano Zampini     if (nisdofs) {
71183e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
71193e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
71203e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
71213e3c6dadSStefano Zampini       }
71223e3c6dadSStefano Zampini     }
71233e3c6dadSStefano Zampini     if (nisneu) {
71243e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
71253e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7126312be037SStefano Zampini     }
712730368db7SStefano Zampini     if (nisvert) {
712830368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
712930368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
713030368db7SStefano Zampini     }
7131f9eb5b7dSStefano Zampini 
7132f9eb5b7dSStefano Zampini     /* get some info after set from options */
7133f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7134f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
71354f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
71366e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7137f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7138f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7139f9eb5b7dSStefano Zampini     }
714039f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
71414f3a063dSStefano Zampini     if (isredundant) {
71424f3a063dSStefano Zampini       KSP inner_ksp;
71434f3a063dSStefano Zampini       PC  inner_pc;
71444f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
71454f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
71464f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
71474f3a063dSStefano Zampini     }
7148f9eb5b7dSStefano Zampini 
714957de7509SStefano Zampini     /* parameters which miss an API */
715057de7509SStefano Zampini     if (isbddc) {
7151720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7152720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
715357de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
715427b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
715527b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7156a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7157a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7158a198735bSStefano Zampini         IS                     row,col;
7159a198735bSStefano Zampini         const PetscInt         *gidxs;
7160a198735bSStefano Zampini         PetscInt               n,st,M,N;
7161a198735bSStefano Zampini 
7162a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7163a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7164a198735bSStefano Zampini         st = st-n;
7165a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7166a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7167a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7168a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7169a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7170a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7171a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7172a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7173a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7174a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7175a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7176a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7177a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7178a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7179a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7180a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7181a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7182a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7183a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7184a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
71858ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7186a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7187720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
718859e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7189720d30f9SStefano Zampini       }
7190d4d8cf7bSStefano Zampini     }
71919881197aSStefano Zampini 
71923301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
71935a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
71943301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
71953301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
71963301b35fSStefano Zampini     }
71973301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
71983301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
71993301b35fSStefano Zampini     }
72003301b35fSStefano Zampini     if (pc->pmat->spd_set) {
72013301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
72023301b35fSStefano Zampini     }
720327b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
720427b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
720527b6a85dSStefano Zampini     }
72066e683305SStefano Zampini     /* set operators */
72075f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
72086e683305SStefano Zampini     if (pcbddc->dbg_flag) {
72096e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
72106e683305SStefano Zampini     }
72116e683305SStefano Zampini   }
72126e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7213b1ecc7b1SStefano Zampini #if 0
7214b9b85e73SStefano Zampini   {
7215b9b85e73SStefano Zampini     PetscViewer viewer;
7216b9b85e73SStefano Zampini     char filename[256];
7217b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7218b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
72196a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7220b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7221f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7222b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7223b9b85e73SStefano Zampini   }
7224b9b85e73SStefano Zampini #endif
7225f9eb5b7dSStefano Zampini 
722698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
722798a51de6SStefano Zampini     Vec crhs,csol;
722804708bb6SStefano Zampini 
7229f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7230f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7231f347579bSStefano Zampini     if (!csol) {
72322a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7233f9eb5b7dSStefano Zampini     }
7234f347579bSStefano Zampini     if (!crhs) {
72352a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7236f347579bSStefano Zampini     }
7237b0f5fe93SStefano Zampini   }
72381ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7239b0f5fe93SStefano Zampini 
7240b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7241b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7242b0f5fe93SStefano Zampini 
7243b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
72444f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
72454f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
72464f1b2e48SStefano Zampini     }
7247b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7248b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7249b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7250b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7251b0f5fe93SStefano Zampini     if (coarse_mat) {
7252b0f5fe93SStefano Zampini       Vec         nullv;
7253b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7254b0f5fe93SStefano Zampini       PetscInt    nl;
7255b0f5fe93SStefano Zampini 
7256b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7257b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7258b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7259b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7260b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7261b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7262b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7263b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7264b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7265b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7266b0f5fe93SStefano Zampini     }
7267b0f5fe93SStefano Zampini   }
7268b0f5fe93SStefano Zampini 
7269b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7270b0f5fe93SStefano Zampini     PetscBool ispreonly;
7271b0f5fe93SStefano Zampini 
7272b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7273b0f5fe93SStefano Zampini       PetscBool isnull;
7274b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7275bef83e63SStefano Zampini       if (isnull) {
7276b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7277b0f5fe93SStefano Zampini       }
7278bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7279b0f5fe93SStefano Zampini     }
7280b0f5fe93SStefano Zampini     /* setup coarse ksp */
7281b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7282cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7283cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
72846e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7285c8587f34SStefano Zampini       KSP       check_ksp;
72862b510759SStefano Zampini       KSPType   check_ksp_type;
7287c8587f34SStefano Zampini       PC        check_pc;
72886e683305SStefano Zampini       Vec       check_vec,coarse_vec;
72896a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
72902b510759SStefano Zampini       PetscInt  its;
72916e683305SStefano Zampini       PetscBool compute_eigs;
72926e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
72936e683305SStefano Zampini       PetscInt  neigs;
72948e185a42SStefano Zampini       const char *prefix;
7295c8587f34SStefano Zampini 
72962b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
72976e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7298422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
729923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7300f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7301e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7302e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7303e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
73042b510759SStefano Zampini       if (ispreonly) {
73052b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
73066e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
73072b510759SStefano Zampini       } else {
7308cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
73096e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7310c8587f34SStefano Zampini       }
7311c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
73126e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
73136e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
73146e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7315a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7316a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7317a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7318a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7319c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7320c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7321c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7322c8587f34SStefano Zampini       /* create random vec */
73232701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7324c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
73256e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7326c8587f34SStefano Zampini       /* solve coarse problem */
73276e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7328cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
73296e683305SStefano Zampini       if (compute_eigs) {
7330854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7331854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
73326e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
73331ae86dd6SStefano Zampini         if (neigs) {
73346e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
73356e683305SStefano Zampini           lambda_min = eigs_r[0];
73366e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
73372701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
73382701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7339cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7340cbcc2c2aSStefano Zampini             }
7341c8587f34SStefano Zampini           }
7342c8587f34SStefano Zampini         }
73431ae86dd6SStefano Zampini       }
7344cbcc2c2aSStefano Zampini 
7345c8587f34SStefano Zampini       /* check coarse problem residual error */
73466e683305SStefano Zampini       if (pcbddc->dbg_flag) {
73476e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
73486e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73496e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7350c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
73516e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
73526e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7353779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
73546e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
73556e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
73566e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
73576e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7358b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7359b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7360b0f5fe93SStefano Zampini         }
73616e683305SStefano Zampini         if (compute_eigs) {
73626e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7363deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7364c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
73656e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
73666e683305SStefano 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);
73676e683305SStefano Zampini           for (i=0;i<neigs;i++) {
73686e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7369c8587f34SStefano Zampini           }
73706e683305SStefano Zampini         }
73716e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
73726e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73736e683305SStefano Zampini       }
7374e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
73752701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7376c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
73776e683305SStefano Zampini       if (compute_eigs) {
73786e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
73796e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7380c8587f34SStefano Zampini       }
73816e683305SStefano Zampini     }
73826e683305SStefano Zampini   }
7383bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7384cbcc2c2aSStefano Zampini   /* print additional info */
7385cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
73866e683305SStefano Zampini     /* waits until all processes reaches this point */
73876e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7388cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7389cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7390cbcc2c2aSStefano Zampini   }
7391cbcc2c2aSStefano Zampini 
73922b510759SStefano Zampini   /* free memory */
7393fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7394c8587f34SStefano Zampini   PetscFunctionReturn(0);
7395c8587f34SStefano Zampini }
7396674ae819SStefano Zampini 
7397f34684f1SStefano Zampini #undef __FUNCT__
7398f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7399f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7400f34684f1SStefano Zampini {
7401f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7402f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7403f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7404dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7405dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
740673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7407dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7408f34684f1SStefano Zampini   PetscErrorCode ierr;
7409f34684f1SStefano Zampini 
7410f34684f1SStefano Zampini   PetscFunctionBegin;
7411f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
74126c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7413dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
74143bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7415dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7416dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
74176583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7418dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7419dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7420dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
74216c4ed002SBarry 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);
7422dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7423dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7424dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7425dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7426dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7427f34684f1SStefano Zampini 
7428f34684f1SStefano Zampini   /* check numbering */
7429f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7430019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7431dc456d91SStefano Zampini     PetscInt    i;
7432b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7433f34684f1SStefano Zampini 
7434f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7435f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7436f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
74371575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7438019a44ceSStefano Zampini     /* counter */
7439019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7440019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7441019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7442019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7443019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7444019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7445f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7446f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7447727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7448f34684f1SStefano Zampini     }
7449f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7450f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7451f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7452e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7453e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7454e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7455e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7456f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7457019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7458f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7459019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
74602c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
746175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7462b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
74632c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
74642c66d082SStefano 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);
7465f34684f1SStefano Zampini       }
7466f34684f1SStefano Zampini     }
7467019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7468b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7469f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7470f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7471f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7472f34684f1SStefano Zampini     }
7473f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7474f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7475e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7476e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7477f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7478f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7479b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7480ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7481ca8b9ea9SStefano Zampini 
7482ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
74833bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7484f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7485f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7486f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7487f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
74884bc2dc4bSStefano 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);
7489f34684f1SStefano Zampini       }
7490f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7491ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7492f34684f1SStefano Zampini     }
7493f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74941575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7495302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7496f34684f1SStefano Zampini   }
74978bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7498f34684f1SStefano Zampini   /* get back data */
7499f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7500f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7501674ae819SStefano Zampini   PetscFunctionReturn(0);
7502674ae819SStefano Zampini }
7503674ae819SStefano Zampini 
7504e456f2a8SStefano Zampini #undef __FUNCT__
7505e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7506a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7507e456f2a8SStefano Zampini {
7508e456f2a8SStefano Zampini   IS             localis_t;
7509a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7510e456f2a8SStefano Zampini   PetscScalar    *vals;
7511e456f2a8SStefano Zampini   PetscErrorCode ierr;
7512e456f2a8SStefano Zampini 
7513e456f2a8SStefano Zampini   PetscFunctionBegin;
7514a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7515e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7516854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7517e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7518e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7519a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7520a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
75211035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7522a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
75231035eff8SStefano Zampini   }
7524a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7525e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7526e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7527a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7528a7dc3881SStefano Zampini   /* now compute set in local ordering */
7529a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7530a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7531a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7532a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7533a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7534ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7535e456f2a8SStefano Zampini       lsize++;
7536e456f2a8SStefano Zampini     }
7537e456f2a8SStefano Zampini   }
7538854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7539a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7540ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7541e456f2a8SStefano Zampini       idxs[lsize++] = i;
7542e456f2a8SStefano Zampini     }
7543e456f2a8SStefano Zampini   }
7544a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7545a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7546e456f2a8SStefano Zampini   *localis = localis_t;
7547e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7548e456f2a8SStefano Zampini }
7549906d46d4SStefano Zampini 
7550b96c3477SStefano Zampini #undef __FUNCT__
7551b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
755208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7553b96c3477SStefano Zampini {
7554a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7555b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7556b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7557a64f4aa4SStefano Zampini   Mat                 S_j;
7558b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7559b96c3477SStefano Zampini   PetscBool           free_used_adj;
7560b96c3477SStefano Zampini   PetscErrorCode      ierr;
7561b96c3477SStefano Zampini 
7562b96c3477SStefano Zampini   PetscFunctionBegin;
7563b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7564b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
756508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7566b96c3477SStefano Zampini     used_xadj = NULL;
7567b96c3477SStefano Zampini     used_adjncy = NULL;
7568b96c3477SStefano Zampini   } else {
756908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
757008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
757108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
757208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7573b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7574b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7575b96c3477SStefano Zampini     } else {
75762fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7577b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7578b96c3477SStefano Zampini       PetscInt       nvtxs;
7579b96c3477SStefano Zampini 
75802fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
75812fffb893SStefano Zampini       if (flg_row) {
7582b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7583b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7584b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7585b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
75862fffb893SStefano Zampini       } else {
75872fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
75882fffb893SStefano Zampini         used_xadj = NULL;
75892fffb893SStefano Zampini         used_adjncy = NULL;
75902fffb893SStefano Zampini       }
75912fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7592b96c3477SStefano Zampini     }
7593b96c3477SStefano Zampini   }
7594d5574798SStefano Zampini 
7595d5574798SStefano Zampini   /* setup sub_schurs data */
7596a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7597df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7598df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7599a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
760091af6908SStefano 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);
7601a64f4aa4SStefano Zampini   } else {
76026816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
76034d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7604a3df083aSStefano Zampini     PetscInt  benign_n;
760572b8c272SStefano Zampini     Mat       change = NULL;
76069d54b7f4SStefano Zampini     Vec       scaling = NULL;
760772b8c272SStefano Zampini     IS        change_primal = NULL;
7608a3df083aSStefano Zampini 
76095feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
76105feab87aSStefano Zampini       PetscInt n_vertices;
76115feab87aSStefano Zampini 
76125feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
76132034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
76145feab87aSStefano Zampini     }
761504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
761604708bb6SStefano Zampini     if (!isseqaij) {
761704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
761804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
761904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
762004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
762104708bb6SStefano Zampini       } else {
7622511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
762304708bb6SStefano Zampini       }
762404708bb6SStefano Zampini     }
7625a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7626a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7627ca92afb2SStefano Zampini     } else {
7628a3df083aSStefano Zampini       benign_n = 0;
7629ca92afb2SStefano Zampini     }
7630b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7631b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7632b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
763372b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
763422db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7635b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
763622db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7637b7ab4a40SStefano Zampini     }
7638b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7639b7ab4a40SStefano 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 */
7640b7ab4a40SStefano Zampini     if (need_change) {
764188c03ad3SStefano Zampini       PC_IS   *pcisf;
764288c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
764388c03ad3SStefano Zampini       PC      pcf;
764488c03ad3SStefano Zampini 
7645e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
764688c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
764788c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
764888c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
764988c03ad3SStefano Zampini       /* hacks */
765088c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
765172b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
765272b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
765372b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
765472b8c272SStefano Zampini       pcisf->n = pcis->n;
765572b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
765688c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
765788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
765888c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
765988c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
766088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
766188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
766272b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
766388c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
766488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
766572b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
766672b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
766772b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
766872b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
766972b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
767088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
767172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
767288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
767388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
767488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
767588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
767688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
767788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
767888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
767988c03ad3SStefano Zampini     }
76809d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
768191af6908SStefano 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);
768272b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
768372b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7684ca92afb2SStefano Zampini   }
7685d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7686b96c3477SStefano Zampini 
7687b96c3477SStefano Zampini   /* free adjacency */
7688b96c3477SStefano Zampini   if (free_used_adj) {
7689b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7690b96c3477SStefano Zampini   }
7691b96c3477SStefano Zampini   PetscFunctionReturn(0);
7692b96c3477SStefano Zampini }
7693b96c3477SStefano Zampini 
7694b96c3477SStefano Zampini #undef __FUNCT__
7695b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
769608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7697b96c3477SStefano Zampini {
7698b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7699b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7700b96c3477SStefano Zampini   PCBDDCGraph         graph;
7701b96c3477SStefano Zampini   PetscErrorCode      ierr;
7702b96c3477SStefano Zampini 
7703b96c3477SStefano Zampini   PetscFunctionBegin;
7704b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
770508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
77063301b35fSStefano Zampini     IS       verticesIS,verticescomm;
77073301b35fSStefano Zampini     PetscInt vsize,*idxs;
7708b96c3477SStefano Zampini 
7709b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
77103301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
77113301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
77123301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
77133301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7714c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7715b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7716be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7717441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
77183301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7719b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7720b96c3477SStefano Zampini   } else {
7721b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7722b96c3477SStefano Zampini   }
7723e4d548c7SStefano Zampini   /* print some info */
7724e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7725e4d548c7SStefano Zampini     IS       vertices;
7726e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7727c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7728e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7729e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7730e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7731e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7732e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7733e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7734e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7735e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7736e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7737c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7738e4d548c7SStefano Zampini   }
7739b96c3477SStefano Zampini 
7740b96c3477SStefano Zampini   /* sub_schurs init */
7741b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7742b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7743b334f244SStefano Zampini   }
7744b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7745a64f4aa4SStefano Zampini 
7746b96c3477SStefano Zampini   /* free graph struct */
774708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7748b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7749b96c3477SStefano Zampini   }
7750b96c3477SStefano Zampini   PetscFunctionReturn(0);
7751b96c3477SStefano Zampini }
7752fa34dd3eSStefano Zampini 
7753fa34dd3eSStefano Zampini #undef __FUNCT__
7754fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7755fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7756fa34dd3eSStefano Zampini {
7757fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7758fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7759fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7760fa34dd3eSStefano Zampini 
7761fa34dd3eSStefano Zampini   PetscFunctionBegin;
7762fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7763fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
77644f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7765fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
77664f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
776775c01103SStefano Zampini     PetscReal      norm;
7768fa34dd3eSStefano Zampini     PetscInt       i;
7769fa34dd3eSStefano Zampini 
7770fa34dd3eSStefano Zampini     /* B0 and B0_B */
7771fa34dd3eSStefano Zampini     if (zerodiag) {
7772fa34dd3eSStefano Zampini       IS       dummy;
7773fa34dd3eSStefano Zampini 
77744f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
77754f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7776fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7777fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7778fa34dd3eSStefano Zampini     }
7779fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7780fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7781fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7782fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7783fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7784fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7785fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7786fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7787fa34dd3eSStefano Zampini     /* S_j */
7788fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7789fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7790fa34dd3eSStefano Zampini 
7791fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7792fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7793fa34dd3eSStefano Zampini     /* continuous in primal space */
7794fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7795fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7796fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7797fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
77984f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
77994f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7800fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7801fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7802fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7803fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7804fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7805fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7806fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7807fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7808fa34dd3eSStefano Zampini 
7809fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7810fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7811fa34dd3eSStefano Zampini     /* local with Schur */
7812fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7813fa34dd3eSStefano Zampini     if (zerodiag) {
7814fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78154f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7816fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7817fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7818fa34dd3eSStefano Zampini     }
7819fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7820fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7821fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7822fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7823fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7824fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7825fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7826fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7827fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7828fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7829fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7830fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7831fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7832fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7833fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7834fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7835fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7836fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7837fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7838fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7839fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7840fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7841fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7842fa34dd3eSStefano Zampini     if (zerodiag) {
7843fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7844fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78454f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7846fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7847fa34dd3eSStefano Zampini     }
7848fa34dd3eSStefano Zampini     /* BDDC */
7849fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7850fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7851fa34dd3eSStefano Zampini 
7852fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7853fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7854fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7855fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
78564f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
78574f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7858fa34dd3eSStefano Zampini     }
78594f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7860fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7861fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7862fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7863fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7864fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7865fa34dd3eSStefano Zampini   }
7866fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7867fa34dd3eSStefano Zampini }
7868