xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision c215121408244d2ea9de89ce7d74438eb25d4cd7)
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;
115*c2151214SStefano Zampini   ISLocalToGlobalMapping el2g,vl2g,fl2g;
116a13144ffSStefano Zampini   MPI_Comm               comm;
117*c2151214SStefano Zampini   IS                     lned,primals,allprimals,nedfieldlocal;
118*c2151214SStefano Zampini   IS                     *eedges,*extrows,*extcols,*alleedges;
119*c2151214SStefano 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;
123*c2151214SStefano 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;
128*c2151214SStefano 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);
140*c2151214SStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(el2g,&n);CHKERRQ(ierr);
141a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
142a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
143*c2151214SStefano 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 
153*c2151214SStefano Zampini   /* Get discrete gradient
154*c2151214SStefano 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;
158*c2151214SStefano Zampini   field      = pcbddc->nedfield;
159*c2151214SStefano 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);
160*c2151214SStefano Zampini   if (pcbddc->n_ISForDofsLocal && field > -1) {
161*c2151214SStefano Zampini     ierr          = PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field]);CHKERRQ(ierr);
162*c2151214SStefano Zampini     nedfieldlocal = pcbddc->ISForDofsLocal[field];
163*c2151214SStefano Zampini     ierr          = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
164*c2151214SStefano Zampini   } else {
165*c2151214SStefano Zampini     PetscBool testnedfield = PETSC_FALSE;
166*c2151214SStefano Zampini     ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_nedelec_field",&testnedfield,NULL);CHKERRQ(ierr);
167*c2151214SStefano Zampini     if (!testnedfield) {
168*c2151214SStefano Zampini       ne            = n;
169*c2151214SStefano Zampini       nedfieldlocal = NULL;
170*c2151214SStefano Zampini     } else {
171*c2151214SStefano Zampini       /* ierr = ISCreateStride(comm,n,0,1,&nedfieldlocal);CHKERRQ(ierr); */
172*c2151214SStefano Zampini       ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
173*c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
174*c2151214SStefano Zampini       ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
175*c2151214SStefano Zampini       for (i=0;i<n;i++) matis->sf_leafdata[i] = 1;
176*c2151214SStefano Zampini       ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
177*c2151214SStefano Zampini       ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
178*c2151214SStefano Zampini       ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
179*c2151214SStefano Zampini       ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
180*c2151214SStefano Zampini       for (i=0,cum=0;i<n;i++) {
181*c2151214SStefano Zampini         if (matis->sf_leafdata[i] > 1) {
182*c2151214SStefano Zampini           matis->sf_leafdata[cum++] = i;
183*c2151214SStefano Zampini         }
184*c2151214SStefano Zampini       }
185*c2151214SStefano Zampini       ierr = ISCreateGeneral(comm,cum,matis->sf_leafdata,PETSC_COPY_VALUES,&nedfieldlocal);CHKERRQ(ierr);
186*c2151214SStefano Zampini       ierr = ISGetLocalSize(nedfieldlocal,&ne);CHKERRQ(ierr);
187*c2151214SStefano Zampini     }
188*c2151214SStefano Zampini   }
189a13144ffSStefano Zampini 
190*c2151214SStefano Zampini   if (nedfieldlocal) { /* merge with previous code when testing is done */
191*c2151214SStefano Zampini     IS is;
192*c2151214SStefano Zampini 
193*c2151214SStefano Zampini     /* need to map from the local Nedelec field to local numbering */
194*c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g);CHKERRQ(ierr);
195*c2151214SStefano Zampini     /* need to map from the local Nedelec field to global numbering */
196*c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(el2g,nedfieldlocal,&is);CHKERRQ(ierr);
197*c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&el2g);CHKERRQ(ierr);
198*c2151214SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
199*c2151214SStefano Zampini   } else {
200*c2151214SStefano Zampini     ierr = PetscObjectReference((PetscObject)el2g);CHKERRQ(ierr);
201*c2151214SStefano Zampini     fl2g = NULL;
202*c2151214SStefano 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) */
210*c2151214SStefano Zampini   ierr = MatISSetUpSF(pc->pmat);CHKERRQ(ierr);
211*c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr);
212*c2151214SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,pc->pmat->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
213*c2151214SStefano Zampini   if (nedfieldlocal) {
214*c2151214SStefano Zampini     ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
215*c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1;
216*c2151214SStefano Zampini     ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
217*c2151214SStefano Zampini   } else {
218*c2151214SStefano Zampini     for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1;
219*c2151214SStefano Zampini   }
220*c2151214SStefano Zampini   ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
221*c2151214SStefano Zampini   ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM);CHKERRQ(ierr);
222*c2151214SStefano Zampini   ierr = MatGetOwnershipRange(G,&rst,NULL);CHKERRQ(ierr);
223*c2151214SStefano Zampini   for (i=0,cum=0;i<pc->pmat->rmap->n;i++) {
224*c2151214SStefano Zampini     if (matis->sf_rootdata[i] < 2) {
225*c2151214SStefano Zampini       matis->sf_rootdata[cum++] = i + rst;
226*c2151214SStefano Zampini     }
227*c2151214SStefano 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);
230*c2151214SStefano 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 */
248*c2151214SStefano 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);
267*c2151214SStefano 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) {
271*c2151214SStefano Zampini     IS is;
272*c2151214SStefano Zampini 
273*c2151214SStefano Zampini     if (fl2g) {
274*c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is);CHKERRQ(ierr);
275*c2151214SStefano Zampini     } else {
276*c2151214SStefano Zampini       is = pcbddc->DirichletBoundariesLocal;
277*c2151214SStefano Zampini     }
278*c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
279*c2151214SStefano 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     }
285*c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
286*c2151214SStefano Zampini     if (fl2g) {
287*c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
288*c2151214SStefano Zampini     }
289a13144ffSStefano Zampini   }
290a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
291*c2151214SStefano Zampini     IS is;
292*c2151214SStefano Zampini 
293*c2151214SStefano Zampini     if (fl2g) {
294*c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is);CHKERRQ(ierr);
295*c2151214SStefano Zampini     } else {
296*c2151214SStefano Zampini       is = pcbddc->NeumannBoundariesLocal;
297*c2151214SStefano Zampini     }
298*c2151214SStefano Zampini     ierr = ISGetLocalSize(is,&cum);CHKERRQ(ierr);
299*c2151214SStefano 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     }
305*c2151214SStefano Zampini     ierr = ISRestoreIndices(is,&idxs);CHKERRQ(ierr);
306*c2151214SStefano Zampini     if (fl2g) {
307*c2151214SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
308a13144ffSStefano Zampini     }
309*c2151214SStefano Zampini   }
310*c2151214SStefano 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);
314a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
315a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
316a13144ffSStefano Zampini     PetscInt j;
317a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) marks[shared[i][j]]++;
318a13144ffSStefano Zampini   }
319a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
320a13144ffSStefano Zampini   cum  = 0;
3214e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
322dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
323a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
324dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
325dec27d64SStefano Zampini     if (!marks[i] || (marks[i] == 1 && !PetscBTLookup(btb,i))) {
326a13144ffSStefano Zampini       marks[cum++] = i;
327dec27d64SStefano Zampini       continue;
328dec27d64SStefano Zampini     }
329dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
330dec27d64SStefano Zampini     if (!conforming && ii[i+1]-ii[i] != order + 1) {
331a13144ffSStefano Zampini       marks[cum++] = i;
332a13144ffSStefano Zampini       ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
333a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
334a13144ffSStefano Zampini         ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
335a13144ffSStefano Zampini       }
336a13144ffSStefano Zampini     }
337dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
338dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
339dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
340dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
341a13144ffSStefano Zampini     }
342dec27d64SStefano Zampini   }
343dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
3444e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
3454e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
346a13144ffSStefano Zampini   /* identify splitpoints and corner candidates: TODO variable order */
3474e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
348a13144ffSStefano Zampini   if (print) {
3494e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
3504e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
3514e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
352a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
353a13144ffSStefano Zampini   }
354a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
355dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
356a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
357dec27d64SStefano Zampini     PetscInt ord = order, test = ii[i+1]-ii[i];
358dec27d64SStefano Zampini     if (!order) {
359dec27d64SStefano Zampini       PetscReal vorder = 0.;
360dec27d64SStefano Zampini 
361dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
362dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
363dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
364dec27d64SStefano Zampini       ord  = 1;
365dec27d64SStefano Zampini     }
366a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
367dec27d64SStefano 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);
368a13144ffSStefano Zampini #endif
369dec27d64SStefano Zampini     if (test >= 3*ord) { /* splitpoints */
370a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
371a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
372dec27d64SStefano Zampini     } else if (test == ord) {
373a13144ffSStefano Zampini       if (order == 1) {
374a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
375a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
376a13144ffSStefano Zampini       } else {
377a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
378a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
379a13144ffSStefano Zampini       }
380a13144ffSStefano Zampini     }
381a13144ffSStefano Zampini   }
382dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
383a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
385a13144ffSStefano Zampini 
386a13144ffSStefano Zampini   /* Get the local G^T explicitly */
387a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
3884e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
389a13144ffSStefano Zampini   if (print) {
390a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"initial_lGt");CHKERRQ(ierr);
391a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
392a13144ffSStefano Zampini   }
393a13144ffSStefano Zampini 
3944e64d54eSstefano_zampini   /* Mark interior nodal dofs */
395a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
3964e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
397a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
398a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
3994e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
400a13144ffSStefano Zampini     }
401a13144ffSStefano Zampini   }
402a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
403a13144ffSStefano Zampini 
404a13144ffSStefano Zampini   /* communicate corners and splitpoints */
405a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
406a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
408a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
409a13144ffSStefano Zampini 
410a13144ffSStefano Zampini   if (print) {
411a13144ffSStefano Zampini     IS tbz;
412a13144ffSStefano Zampini 
413a13144ffSStefano Zampini     cum = 0;
414a13144ffSStefano Zampini     for (i=0;i<nv;i++)
415a13144ffSStefano Zampini       if (sfvleaves[i])
416a13144ffSStefano Zampini         vmarks[cum++] = i;
417a13144ffSStefano Zampini 
418a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
419a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
420a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
421a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
422a13144ffSStefano Zampini   }
423a13144ffSStefano Zampini 
424a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
425a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
426a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
427a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
428a13144ffSStefano Zampini 
4294e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
4304e64d54eSstefano_zampini      and interior nodal dofs */
431a13144ffSStefano Zampini   cum = 0;
432a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
433a13144ffSStefano Zampini     if (sfvleaves[i]) {
434a13144ffSStefano Zampini       vmarks[cum++] = i;
435a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
436a13144ffSStefano Zampini     }
4374e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
438a13144ffSStefano Zampini   }
4394e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
440a13144ffSStefano Zampini   if (print) {
441a13144ffSStefano Zampini     IS tbz;
442a13144ffSStefano Zampini 
443a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
4444e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
445a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
446a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
447a13144ffSStefano Zampini   }
448a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
449a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
450a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
451a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
452a13144ffSStefano Zampini 
453a13144ffSStefano Zampini   /* Recompute G */
454a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
455a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
456a13144ffSStefano Zampini   if (print) {
457a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
458a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
459a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
460a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
461a13144ffSStefano Zampini   }
462a13144ffSStefano Zampini 
463a13144ffSStefano Zampini   /* Get primal dofs (if any) */
464a13144ffSStefano Zampini   cum = 0;
465a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
466a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
467a13144ffSStefano Zampini   }
468*c2151214SStefano Zampini   if (fl2g) {
469*c2151214SStefano Zampini     ierr = ISLocalToGlobalMappingApply(fl2g,cum,marks,marks);CHKERRQ(ierr);
470*c2151214SStefano Zampini   }
471a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
472a13144ffSStefano Zampini   if (print) {
473a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
474a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
475a13144ffSStefano Zampini   }
476a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
477*c2151214SStefano Zampini   /* TODO: what if the user passed in some of them ?  */
478a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
479a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
480a13144ffSStefano Zampini 
481a13144ffSStefano Zampini   /* Compute edge connectivity */
482a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
483a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
484a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
485d904f53bSStefano Zampini   if (done && i && ii && jj) { /* when lG is empty, don't pass pointers */
486*c2151214SStefano Zampini     if (fl2g) {
487*c2151214SStefano Zampini       PetscBT   btf;
488*c2151214SStefano Zampini       PetscInt  *iia,*jja,*iiu,*jju;
489*c2151214SStefano Zampini       PetscBool rest = PETSC_FALSE,free = PETSC_FALSE;
490*c2151214SStefano Zampini 
491*c2151214SStefano Zampini       /* create CSR for all local dofs */
492*c2151214SStefano Zampini       ierr = PetscMalloc1(n+1,&iia);CHKERRQ(ierr);
493*c2151214SStefano Zampini       if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */
494*c2151214SStefano 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);
495*c2151214SStefano Zampini         iiu = pcbddc->mat_graph->xadj;
496*c2151214SStefano Zampini         jju = pcbddc->mat_graph->adjncy;
497*c2151214SStefano Zampini       } else if (pcbddc->use_local_adj) {
498*c2151214SStefano Zampini         rest = PETSC_TRUE;
499*c2151214SStefano Zampini         ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
500*c2151214SStefano Zampini       } else {
501*c2151214SStefano Zampini         free   = PETSC_TRUE;
502*c2151214SStefano Zampini         ierr   = PetscMalloc2(n+1,&iiu,n,&jju);CHKERRQ(ierr);
503*c2151214SStefano Zampini         iiu[0] = 0;
504*c2151214SStefano Zampini         for (i=0;i<n;i++) {
505*c2151214SStefano Zampini           iiu[i+1] = i+1;
506*c2151214SStefano Zampini           jju[i]   = -1;
507d904f53bSStefano Zampini         }
508*c2151214SStefano Zampini       }
509*c2151214SStefano Zampini 
510*c2151214SStefano Zampini       /* import sizes of CSR */
511*c2151214SStefano Zampini       iia[0] = 0;
512*c2151214SStefano Zampini       for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i];
513*c2151214SStefano Zampini 
514*c2151214SStefano Zampini       /* overwrite entries corresponding to the Nedelec field */
515*c2151214SStefano Zampini       ierr = PetscBTCreate(n,&btf);CHKERRQ(ierr);
516*c2151214SStefano Zampini       ierr = ISGetIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
517*c2151214SStefano Zampini       for (i=0;i<ne;i++) {
518*c2151214SStefano Zampini         ierr = PetscBTSet(btf,idxs[i]);CHKERRQ(ierr);
519*c2151214SStefano Zampini         iia[idxs[i]+1] = ii[i+1]-ii[i];
520*c2151214SStefano Zampini       }
521*c2151214SStefano Zampini 
522*c2151214SStefano Zampini       /* iia in CSR */
523*c2151214SStefano Zampini       for (i=0;i<n;i++) iia[i+1] += iia[i];
524*c2151214SStefano Zampini 
525*c2151214SStefano Zampini       /* jja in CSR */
526*c2151214SStefano Zampini       ierr = PetscMalloc1(iia[n],&jja);CHKERRQ(ierr);
527*c2151214SStefano Zampini       for (i=0;i<n;i++)
528*c2151214SStefano Zampini         if (!PetscBTLookup(btf,i))
529*c2151214SStefano Zampini           for (j=0;j<iiu[i+1]-iiu[i];j++)
530*c2151214SStefano Zampini             jja[iia[i]+j] = jju[iiu[i]+j];
531*c2151214SStefano Zampini 
532*c2151214SStefano Zampini       /* map edge dofs connectivity */
533*c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj);CHKERRQ(ierr);
534*c2151214SStefano Zampini       for (i=0;i<ne;i++) {
535*c2151214SStefano Zampini         PetscInt e = idxs[i];
536*c2151214SStefano Zampini         for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j];
537*c2151214SStefano Zampini       }
538*c2151214SStefano Zampini 
539*c2151214SStefano Zampini       ierr = ISRestoreIndices(nedfieldlocal,&idxs);CHKERRQ(ierr);
540*c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER);CHKERRQ(ierr);
541*c2151214SStefano Zampini       if (rest) {
542*c2151214SStefano Zampini         ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done);CHKERRQ(ierr);
543*c2151214SStefano Zampini       }
544*c2151214SStefano Zampini       if (free) {
545*c2151214SStefano Zampini         ierr = PetscFree2(iiu,jju);CHKERRQ(ierr);
546*c2151214SStefano Zampini       }
547*c2151214SStefano Zampini       ierr = PetscBTDestroy(&btf);CHKERRQ(ierr);
548*c2151214SStefano Zampini     } else {
549*c2151214SStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
550*c2151214SStefano Zampini     }
551*c2151214SStefano Zampini   }
552*c2151214SStefano Zampini 
553a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
554a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
555a13144ffSStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
556a13144ffSStefano Zampini 
557a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
558a13144ffSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
559*c2151214SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
560a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
561a13144ffSStefano Zampini 
562*c2151214SStefano Zampini   if (fl2g) {
563*c2151214SStefano Zampini     ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
564*c2151214SStefano Zampini     ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
565*c2151214SStefano Zampini     for (i=0;i<nee;i++) {
566*c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
567*c2151214SStefano Zampini     }
568*c2151214SStefano Zampini   } else {
569*c2151214SStefano Zampini     eedges  = alleedges;
570*c2151214SStefano Zampini     primals = allprimals;
571*c2151214SStefano Zampini   }
572*c2151214SStefano Zampini 
573a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
574a13144ffSStefano Zampini   ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
575*c2151214SStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
576*c2151214SStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
577*c2151214SStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
578*c2151214SStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
579*c2151214SStefano Zampini   if (print) {
580*c2151214SStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
581*c2151214SStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
582*c2151214SStefano Zampini   }
583*c2151214SStefano Zampini 
584*c2151214SStefano Zampini   maxsize = 0;
585a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
586a13144ffSStefano Zampini     PetscInt size,mark = i+1;
587a13144ffSStefano Zampini 
588a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
589a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
590a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
591a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
592a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
593a13144ffSStefano Zampini   }
594a13144ffSStefano Zampini 
595a13144ffSStefano Zampini   /* Find coarse edge endpoints */
596a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
597a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
598a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
599a13144ffSStefano Zampini     PetscInt mark = i+1,size;
600a13144ffSStefano Zampini 
601a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
602a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
603a13144ffSStefano Zampini     if (print) {
604a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
605a13144ffSStefano Zampini       ISView(eedges[i],NULL);
606a13144ffSStefano Zampini     }
607a13144ffSStefano Zampini     for (j=0;j<size;j++) {
608a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
609a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
610a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
611a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
612a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
613a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
614a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
615a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      candidate? %d\n",(PetscBool)(PetscBTLookup(btvcand,jj[k])));
616a13144ffSStefano Zampini           PetscInt  k2;
617a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
618a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
619*c2151214SStefano 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]));
620*c2151214SStefano Zampini             /* it's a corner if either is connected with an edge dof belonging to a different cc or
621*c2151214SStefano Zampini                if the edge dof lie on the natural part of the boundary */
622*c2151214SStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) {
623a13144ffSStefano Zampini               corner = PETSC_TRUE;
624a13144ffSStefano Zampini               break;
625a13144ffSStefano Zampini             }
626a13144ffSStefano Zampini           }
627a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
628a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
629a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
630a13144ffSStefano Zampini           } else {
631a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
632a13144ffSStefano Zampini           }
633a13144ffSStefano Zampini         }
634a13144ffSStefano Zampini       }
635a13144ffSStefano Zampini     }
636a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
637a13144ffSStefano Zampini   }
638a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
639a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
640*c2151214SStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
641a13144ffSStefano Zampini 
642a13144ffSStefano Zampini   /* Reset marked primal dofs */
643a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
644a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
645a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
646a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
647a13144ffSStefano Zampini 
648a13144ffSStefano Zampini   /* Compute extended cols indices */
649a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG ,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
650a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
651a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
652a13144ffSStefano Zampini   i   *= maxsize;
653a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extcols);CHKERRQ(ierr);
654a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&emarks);CHKERRQ(ierr);
655a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
656a13144ffSStefano Zampini   eerr = PETSC_FALSE;
657a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
658a13144ffSStefano Zampini     PetscInt size;
659a13144ffSStefano Zampini 
660a13144ffSStefano Zampini     cum  = 0;
661a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
662a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
663a13144ffSStefano Zampini     for (j=0;j<size;j++) {
664a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
665a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
666a13144ffSStefano Zampini     }
667a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
668a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
669a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
670a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
671a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
672a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
673a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
674a13144ffSStefano Zampini     if (cum != size -1) {
675a13144ffSStefano Zampini       emarks[i] = 1;
676a13144ffSStefano Zampini       if (print) {
677a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
678a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
679a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
680a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
681a13144ffSStefano Zampini       }
682a13144ffSStefano Zampini       eerr = PETSC_TRUE;
683a13144ffSStefano Zampini     }
684a13144ffSStefano Zampini   }
6854e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
686a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
687a13144ffSStefano Zampini   if (done) {
688a13144ffSStefano Zampini     PetscInt *newprimals;
689a13144ffSStefano Zampini 
690a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
691a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
692a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
693a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
694a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
695a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
696a13144ffSStefano Zampini       if (emarks[i]) {
697a13144ffSStefano Zampini         PetscInt size,mark = i+1;
698a13144ffSStefano Zampini 
699a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
700a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
701*c2151214SStefano Zampini         /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */
702a13144ffSStefano Zampini         for (j=0;j<size;j++) {
703a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
704a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
705a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
706a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
707a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
708a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
709a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
710a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
711a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
712a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
713a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
714a13144ffSStefano Zampini                   /* finally set the new corners */
715a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
716a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
717a13144ffSStefano Zampini                   }
718a13144ffSStefano Zampini                 }
719a13144ffSStefano Zampini               }
720a13144ffSStefano Zampini             }
721a13144ffSStefano Zampini           }
722a13144ffSStefano Zampini         }
723a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
724a13144ffSStefano Zampini       }
725a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
726a13144ffSStefano Zampini     }
727a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
728*c2151214SStefano Zampini     if (fl2g) {
729*c2151214SStefano Zampini       ierr = ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals);CHKERRQ(ierr);
730*c2151214SStefano Zampini       ierr = ISDestroy(&primals);CHKERRQ(ierr);
731*c2151214SStefano Zampini       for (i=0;i<nee;i++) {
732*c2151214SStefano Zampini         ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
733*c2151214SStefano Zampini       }
734*c2151214SStefano Zampini       ierr = PetscFree(eedges);CHKERRQ(ierr);
735*c2151214SStefano Zampini     }
736*c2151214SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
737a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
738a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
739a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
740a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
741a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
742*c2151214SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
743*c2151214SStefano Zampini     if (fl2g) {
744*c2151214SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals);CHKERRQ(ierr);
745*c2151214SStefano Zampini       ierr = PetscMalloc1(nee,&eedges);CHKERRQ(ierr);
746*c2151214SStefano Zampini       for (i=0;i<nee;i++) {
747*c2151214SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i]);CHKERRQ(ierr);
748*c2151214SStefano Zampini       }
749*c2151214SStefano Zampini     } else {
750*c2151214SStefano Zampini       eedges  = alleedges;
751*c2151214SStefano Zampini       primals = allprimals;
752*c2151214SStefano Zampini     }
753a13144ffSStefano Zampini 
754a13144ffSStefano Zampini     /* Mark again */
755a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
756a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
757a13144ffSStefano Zampini       PetscInt size,mark = i+1;
758a13144ffSStefano Zampini 
759a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
760a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
761a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
762a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
763a13144ffSStefano Zampini     }
764a13144ffSStefano Zampini     if (print) {
765a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
766a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
767a13144ffSStefano Zampini     }
768a13144ffSStefano Zampini 
769a13144ffSStefano Zampini     /* Recompute extended cols */
770a13144ffSStefano Zampini     eerr = PETSC_FALSE;
771a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
772a13144ffSStefano Zampini       PetscInt size;
773a13144ffSStefano Zampini 
774a13144ffSStefano Zampini       cum  = 0;
775a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
776a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
777a13144ffSStefano Zampini       for (j=0;j<size;j++) {
778a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
779a13144ffSStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) {
780a13144ffSStefano Zampini           if (!PetscBTLookup(btv,jj[k])) {
781a13144ffSStefano Zampini             extrow[cum++] = jj[k];
782a13144ffSStefano Zampini           }
783a13144ffSStefano Zampini         }
784a13144ffSStefano Zampini       }
785a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
786a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
787a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
788a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
789a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
790a13144ffSStefano Zampini       if (cum != size -1) {
791a13144ffSStefano Zampini         if (print) {
792a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
793a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
794a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
795a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
796a13144ffSStefano Zampini         }
797a13144ffSStefano Zampini         eerr = PETSC_TRUE;
798a13144ffSStefano Zampini       }
799a13144ffSStefano Zampini     }
800a13144ffSStefano Zampini   }
801a13144ffSStefano Zampini   ierr = MatRestoreRowIJ( lG,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
802a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
803a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
804a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
805a13144ffSStefano Zampini   /* an error should not occur at this point */
806a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
807a13144ffSStefano Zampini 
8084e64d54eSstefano_zampini   /* Check the number of endpoints */
809*c2151214SStefano Zampini   /* TODO: fix case for circular edge */
8104e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
8114e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8124e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
8134e64d54eSstefano_zampini     PetscInt size, found = 0;
8144e64d54eSstefano_zampini 
8154e64d54eSstefano_zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
8164e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
8174e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
8184e64d54eSstefano_zampini     for (j=0;j<size;j++) {
8194e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
8204e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
8214e64d54eSstefano_zampini         PetscInt vv = jj[k];
8224e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
8234e64d54eSstefano_zampini           found++;
8244e64d54eSstefano_zampini         }
8254e64d54eSstefano_zampini       }
8264e64d54eSstefano_zampini     }
8274e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
8284e64d54eSstefano_zampini     if (found != 2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d\n",found,i);
8294e64d54eSstefano_zampini   }
8304e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
8314e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
8324e64d54eSstefano_zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
8334e64d54eSstefano_zampini 
834a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
835a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
836a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
837a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
838a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
839a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
840a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
841a13144ffSStefano Zampini 
842a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
843a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
844a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
845a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
846a13144ffSStefano Zampini       if (emax < emarks[j]) {
847a13144ffSStefano Zampini         emax = emarks[j];
848a13144ffSStefano Zampini         eemax = j;
849a13144ffSStefano Zampini       }
850a13144ffSStefano Zampini     }
851a13144ffSStefano Zampini     /* not relevant for edges */
852a13144ffSStefano Zampini     if (!eemax) continue;
853a13144ffSStefano Zampini 
854a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
855a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
856*c2151214SStefano 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]);
857a13144ffSStefano Zampini       }
858a13144ffSStefano Zampini     }
859a13144ffSStefano Zampini   }
860a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
861a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
862a13144ffSStefano Zampini #endif
863a13144ffSStefano Zampini 
864a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
865a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
866a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
867a13144ffSStefano Zampini   extmem *= maxsize;
868a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
869a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
870a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
871a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
872a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
873a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
874a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
875a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
876a13144ffSStefano Zampini         mark = marks[jj[j]];
877a13144ffSStefano Zampini 
878a13144ffSStefano Zampini     /* not relevant */
879a13144ffSStefano Zampini     if (!mark) continue;
880a13144ffSStefano Zampini 
881a13144ffSStefano Zampini     /* import extended row */
882a13144ffSStefano Zampini     mark--;
883a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
884a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
885a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
886a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
887a13144ffSStefano Zampini     extrowcum[mark] += size;
888a13144ffSStefano Zampini   }
889a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
890a13144ffSStefano Zampini   cum  = 0;
891a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
892a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
893a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
894a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
895a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
896a13144ffSStefano Zampini   }
897a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
898a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
899a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
900a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
901a13144ffSStefano Zampini 
902a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
903a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
904a13144ffSStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
905a13144ffSStefano Zampini   for (i=0;i<maxsize;i++) vals[i] = 1.;
906a13144ffSStefano Zampini 
907a13144ffSStefano Zampini   /* Create vectors for quadrature rules */
908*c2151214SStefano Zampini   /* TODO preserve other quadratures */
909a13144ffSStefano Zampini   ierr = PetscMalloc1(nquads,&quads);CHKERRQ(ierr);
910a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
911a13144ffSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quads[i],NULL);CHKERRQ(ierr);
912a13144ffSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quads[i],el2g);CHKERRQ(ierr);
913a13144ffSStefano Zampini   }
914a13144ffSStefano Zampini   ierr = PCBDDCNullSpaceCreate(comm,PETSC_FALSE,nquads,quads,&nnsp);CHKERRQ(ierr);
915a13144ffSStefano Zampini 
916a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
917a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
918*c2151214SStefano Zampini   ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n,
919*c2151214SStefano Zampini                        pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr);
920a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
921a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
922a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
923a13144ffSStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,el2g,el2g);CHKERRQ(ierr);
924a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
925a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
926a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
927a13144ffSStefano Zampini 
928a13144ffSStefano Zampini   /* Defaults to identity */
929*c2151214SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
930a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
931a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
932a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
933a13144ffSStefano Zampini 
934a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
935a13144ffSStefano Zampini     Mat Gins = NULL, GKins = NULL;
936a13144ffSStefano Zampini 
937a13144ffSStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],&Gins,&GKins,work,rwork);CHKERRQ(ierr);
938a13144ffSStefano Zampini     if (Gins && GKins) {
939a13144ffSStefano Zampini       PetscScalar    *data;
940a13144ffSStefano Zampini       const PetscInt *rows,*cols;
941a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
942a13144ffSStefano Zampini 
943a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
944a13144ffSStefano Zampini       /* H1 */
945a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
946a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
947a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
948a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
949a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
950a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
951a13144ffSStefano Zampini       /* complement */
952a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
953a13144ffSStefano Zampini       if (ncc > nquads-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet supported ncc %d nquads %d",ncc,nquads);
954a13144ffSStefano 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);
955a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
956a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
957a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
958a13144ffSStefano Zampini       /* Gins kernel quadratures */
959a13144ffSStefano Zampini       for (j=0;j<ncc;j++) {
960a13144ffSStefano Zampini         ierr = VecSetValueLocal(quads[j],cols[nch+j],1.,INSERT_VALUES);CHKERRQ(ierr);
961a13144ffSStefano Zampini       }
962a13144ffSStefano Zampini       /* H1 average */
963a13144ffSStefano Zampini       ierr = VecSetValuesLocal(quads[nquads-1],nch,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
964a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
965a13144ffSStefano Zampini     }
966a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
967a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
968a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
969a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
970a13144ffSStefano Zampini   }
971a13144ffSStefano Zampini 
972a13144ffSStefano Zampini   /* Start assembling */
973a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
974a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
975a13144ffSStefano Zampini     ierr = VecAssemblyBegin(quads[i]);CHKERRQ(ierr);
976a13144ffSStefano Zampini   }
977a13144ffSStefano Zampini 
978a13144ffSStefano Zampini   /* Free */
979*c2151214SStefano Zampini   if (fl2g) {
980*c2151214SStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
981*c2151214SStefano Zampini     for (i=0;i<nee;i++) {
982*c2151214SStefano Zampini       ierr = ISDestroy(&eedges[i]);CHKERRQ(ierr);
983*c2151214SStefano Zampini     }
984*c2151214SStefano Zampini     ierr = PetscFree(eedges);CHKERRQ(ierr);
985*c2151214SStefano Zampini   }
986*c2151214SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals);CHKERRQ(ierr);
987*c2151214SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
988*c2151214SStefano Zampini   ierr = ISDestroy(&nedfieldlocal);CHKERRQ(ierr);
989a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
990a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
991*c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&el2g);CHKERRQ(ierr);
992*c2151214SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&fl2g);CHKERRQ(ierr);
993a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
994a13144ffSStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
995a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
996a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
997a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
998a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
999a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
1000a13144ffSStefano Zampini 
1001a13144ffSStefano Zampini   /* Complete assembling */
1002a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1003a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1004a13144ffSStefano Zampini     ierr = VecAssemblyEnd(quads[i]);CHKERRQ(ierr);
1005a13144ffSStefano Zampini   }
1006a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
1007a13144ffSStefano Zampini     ierr = VecDestroy(&quads[i]);CHKERRQ(ierr);
1008a13144ffSStefano Zampini   }
1009a13144ffSStefano Zampini   ierr = PetscFree(quads);CHKERRQ(ierr);
1010a13144ffSStefano Zampini 
1011a13144ffSStefano Zampini   /* tell PCBDDC the topography has been analyzed */
1012a13144ffSStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
1013a13144ffSStefano Zampini 
1014a13144ffSStefano Zampini   /* set change of basis */
1015a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
1016a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
1017a13144ffSStefano Zampini 
1018a13144ffSStefano Zampini   /* set quadratures */
1019a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
1020a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
1021a13144ffSStefano Zampini 
1022a13144ffSStefano Zampini   PetscFunctionReturn(0);
1023a13144ffSStefano Zampini }
1024a13144ffSStefano Zampini 
1025d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
1026d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
1027d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
1028d8203eabSStefano Zampini #undef __FUNCT__
1029d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
1030d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
1031d8203eabSStefano Zampini {
1032d8203eabSStefano Zampini   PetscErrorCode ierr;
1033d8203eabSStefano Zampini   PetscInt       i;
1034d8203eabSStefano Zampini 
1035d8203eabSStefano Zampini   PetscFunctionBegin;
1036d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
1037d8203eabSStefano Zampini     PetscInt first,last;
1038d8203eabSStefano Zampini 
1039d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
104086fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1041d8203eabSStefano Zampini     if (i>=first && i < last) {
1042d8203eabSStefano Zampini       PetscScalar *data;
1043d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1044d8203eabSStefano Zampini       if (!has_const) {
1045d8203eabSStefano Zampini         data[i-first] = 1.;
1046d8203eabSStefano Zampini       } else {
104786fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
104886fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
1049d8203eabSStefano Zampini       }
1050d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1051d8203eabSStefano Zampini     }
1052d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1053d8203eabSStefano Zampini   }
1054d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
1055d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
1056d8203eabSStefano Zampini     PetscInt first,last;
1057d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
1058d8203eabSStefano Zampini     if (i>=first && i < last) {
1059d8203eabSStefano Zampini       PetscScalar *data;
1060d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
1061d8203eabSStefano Zampini       if (!has_const) {
1062d8203eabSStefano Zampini         data[i-first] = 0.;
1063d8203eabSStefano Zampini       } else {
106486fa73c5SStefano Zampini         data[2*i-first] = 0.;
106586fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
1066d8203eabSStefano Zampini       }
1067d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
1068d8203eabSStefano Zampini     }
1069d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
1070d8203eabSStefano Zampini   }
1071d8203eabSStefano Zampini   PetscFunctionReturn(0);
1072d8203eabSStefano Zampini }
1073d8203eabSStefano Zampini 
1074669cc0f4SStefano Zampini #undef __FUNCT__
1075669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
10768ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
1077669cc0f4SStefano Zampini {
1078a198735bSStefano Zampini   Mat                    loc_divudotp;
1079fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
10808ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
1081669cc0f4SStefano Zampini   IS                     *faces,*edges;
1082669cc0f4SStefano Zampini   PetscScalar            *vals;
1083669cc0f4SStefano Zampini   const PetscScalar      *array;
1084669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
10851ae86dd6SStefano Zampini   PetscMPIInt            rank;
1086a198735bSStefano Zampini   PetscErrorCode         ierr;
1087669cc0f4SStefano Zampini 
1088669cc0f4SStefano Zampini   PetscFunctionBegin;
1089669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1090669cc0f4SStefano Zampini   if (graph->twodim) {
1091669cc0f4SStefano Zampini     lmaxneighs = 2;
1092669cc0f4SStefano Zampini   } else {
1093669cc0f4SStefano Zampini     lmaxneighs = 1;
1094669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
1095669cc0f4SStefano Zampini       const PetscInt *idxs;
1096669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1097669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
1098669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1099669cc0f4SStefano Zampini     }
1100669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
1101669cc0f4SStefano Zampini   }
1102669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1103669cc0f4SStefano Zampini   maxsize = 0;
1104669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1105669cc0f4SStefano Zampini     PetscInt nn;
1106669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1107669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1108669cc0f4SStefano Zampini   }
1109669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1110669cc0f4SStefano Zampini     PetscInt nn;
1111669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1112669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
1113669cc0f4SStefano Zampini   }
1114669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
1115669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
1116669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
11178ae0ca82SStefano Zampini   if (!transpose) {
11188ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
11198ae0ca82SStefano Zampini   } else {
11208ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
11218ae0ca82SStefano Zampini   }
1122669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
11231ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
1124d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
1125669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
11268ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
1127669cc0f4SStefano Zampini   }
1128d8203eabSStefano Zampini 
1129669cc0f4SStefano Zampini   /* compute local quad vec */
1130a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
11318ae0ca82SStefano Zampini   if (!transpose) {
1132a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
11338ae0ca82SStefano Zampini   } else {
11348ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
11358ae0ca82SStefano Zampini   }
1136669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
11378ae0ca82SStefano Zampini   if (!transpose) {
1138a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
11398ae0ca82SStefano Zampini   } else {
11408ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
11418ae0ca82SStefano Zampini   }
1142fa23a32eSStefano Zampini   if (vl2l) {
1143fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1144fa23a32eSStefano Zampini   } else {
1145fa23a32eSStefano Zampini     vins = v;
1146fa23a32eSStefano Zampini   }
1147fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
1148669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
11499a962809SStefano Zampini 
11501ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
11511ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
1152669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
1153669cc0f4SStefano Zampini     const PetscInt    *idxs;
1154669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1155669cc0f4SStefano Zampini 
1156669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
1157669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
1158669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
11591ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1160669cc0f4SStefano Zampini     idx = -(idx+1);
1161669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1162669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
1163669cc0f4SStefano Zampini   }
1164669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
1165669cc0f4SStefano Zampini     const PetscInt    *idxs;
1166669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
1167669cc0f4SStefano Zampini 
1168669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
1169669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
1170669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
11711ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
1172669cc0f4SStefano Zampini     idx = -(idx+1);
1173669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1174669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
1175669cc0f4SStefano Zampini   }
1176c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1177fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1178fa23a32eSStefano Zampini   if (vl2l) {
1179fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1180fa23a32eSStefano Zampini   }
1181669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1182669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1183669cc0f4SStefano Zampini 
1184669cc0f4SStefano Zampini   /* assemble near null space */
1185669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1186669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1187669cc0f4SStefano Zampini   }
1188669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1189669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1190669cc0f4SStefano Zampini   }
1191669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1192669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1193669cc0f4SStefano Zampini }
1194669cc0f4SStefano Zampini 
1195669cc0f4SStefano Zampini 
1196a3df083aSStefano Zampini #undef __FUNCT__
11971f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
11981f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
11991f4df5f7SStefano Zampini {
12001f4df5f7SStefano Zampini   PetscErrorCode ierr;
12011f4df5f7SStefano Zampini   Vec            local,global;
12021f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12031f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
12041f4df5f7SStefano Zampini 
12051f4df5f7SStefano Zampini   PetscFunctionBegin;
12061f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
12071f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
12081f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
12091f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
12101f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
12111f4df5f7SStefano Zampini       PetscInt i;
12121f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12131f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
12141f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12151f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12161f4df5f7SStefano Zampini       }
12171f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
12181f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
12191f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
12201f4df5f7SStefano Zampini     }
12211f4df5f7SStefano Zampini   } else {
1222986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
12231f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1224986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1225986cdee1SStefano Zampini       if (i > 1) {
1226986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
12271f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
12281f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12291f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
12301f4df5f7SStefano Zampini         }
12311f4df5f7SStefano Zampini       }
12321f4df5f7SStefano Zampini     }
1233986cdee1SStefano Zampini   }
12341f4df5f7SStefano Zampini 
12351f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
12361f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
12371f4df5f7SStefano Zampini   }
12381f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
12391f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
12401f4df5f7SStefano Zampini   }
12411f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
12421f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
12431f4df5f7SStefano Zampini   }
12441f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
12451f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
12461f4df5f7SStefano Zampini   PetscFunctionReturn(0);
12471f4df5f7SStefano Zampini }
12481f4df5f7SStefano Zampini 
12491f4df5f7SStefano Zampini #undef __FUNCT__
12503e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
12513e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
12523e589ea0SStefano Zampini {
12533e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
12543e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
12553e589ea0SStefano Zampini   PetscErrorCode    ierr;
12563e589ea0SStefano Zampini 
12573e589ea0SStefano Zampini   PetscFunctionBegin;
12583e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
12593e589ea0SStefano Zampini     PetscFunctionReturn(0);
12603e589ea0SStefano Zampini   }
12613e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
12623e589ea0SStefano Zampini     Vec swap;
12633e589ea0SStefano Zampini 
12643e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
12653e589ea0SStefano Zampini     swap = pcbddc->work_change;
12663e589ea0SStefano Zampini     pcbddc->work_change = r;
12673e589ea0SStefano Zampini     r = swap;
12683e589ea0SStefano Zampini   }
12693e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12703e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12713e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
12723e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
12733e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12743e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12753e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
12763e589ea0SStefano Zampini     Vec swap;
12773e589ea0SStefano Zampini 
12783e589ea0SStefano Zampini     swap = r;
12793e589ea0SStefano Zampini     r = pcbddc->work_change;
12803e589ea0SStefano Zampini     pcbddc->work_change = swap;
12813e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
12823e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
12833e589ea0SStefano Zampini   }
12843e589ea0SStefano Zampini   PetscFunctionReturn(0);
12853e589ea0SStefano Zampini }
12863e589ea0SStefano Zampini 
12873e589ea0SStefano Zampini #undef __FUNCT__
1288a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1289a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1290a3df083aSStefano Zampini {
1291a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1292a3df083aSStefano Zampini   PetscErrorCode          ierr;
1293a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1294a3df083aSStefano Zampini 
1295a3df083aSStefano Zampini   PetscFunctionBegin;
1296a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1297a3df083aSStefano Zampini   if (transpose) {
1298a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1299a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1300a3df083aSStefano Zampini   } else {
1301a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1302a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1303a3df083aSStefano Zampini   }
1304a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1305a3df083aSStefano Zampini   if (apply_right) {
1306a3df083aSStefano Zampini     const PetscScalar *ax;
1307a3df083aSStefano Zampini     PetscInt          nl,i;
1308a3df083aSStefano Zampini 
1309a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1310a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1311a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1312a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1313a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1314a3df083aSStefano Zampini       PetscScalar    sum,val;
1315a3df083aSStefano Zampini       const PetscInt *idxs;
1316a3df083aSStefano Zampini       PetscInt       nz,j;
1317a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1318a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1319a3df083aSStefano Zampini       sum = 0.;
1320a3df083aSStefano Zampini       if (ctx->apply_p0) {
1321a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1322a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1323a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1324a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1325a3df083aSStefano Zampini         }
1326a3df083aSStefano Zampini       } else {
1327a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1328a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1329a3df083aSStefano Zampini         }
1330a3df083aSStefano Zampini       }
1331a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1332a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1333a3df083aSStefano Zampini     }
1334a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1335a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1336a3df083aSStefano Zampini   }
1337a3df083aSStefano Zampini   if (transpose) {
1338a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1339a3df083aSStefano Zampini   } else {
1340a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1341a3df083aSStefano Zampini   }
1342a3df083aSStefano Zampini   if (reset_x) {
1343a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1344a3df083aSStefano Zampini   }
1345a3df083aSStefano Zampini   if (apply_left) {
1346a3df083aSStefano Zampini     PetscScalar *ay;
1347a3df083aSStefano Zampini     PetscInt    i;
1348a3df083aSStefano Zampini 
1349a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1350a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1351a3df083aSStefano Zampini       PetscScalar    sum,val;
1352a3df083aSStefano Zampini       const PetscInt *idxs;
1353a3df083aSStefano Zampini       PetscInt       nz,j;
1354a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1355a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1356a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1357a3df083aSStefano Zampini       if (ctx->apply_p0) {
1358a3df083aSStefano Zampini         sum = 0.;
1359a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1360a3df083aSStefano Zampini           sum += ay[idxs[j]];
1361a3df083aSStefano Zampini           ay[idxs[j]] += val;
1362a3df083aSStefano Zampini         }
1363a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1364a3df083aSStefano Zampini       } else {
1365a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1366a3df083aSStefano Zampini           ay[idxs[j]] += val;
1367a3df083aSStefano Zampini         }
1368a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1369a3df083aSStefano Zampini       }
1370a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1371a3df083aSStefano Zampini     }
1372a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1373a3df083aSStefano Zampini   }
1374a3df083aSStefano Zampini   PetscFunctionReturn(0);
1375a3df083aSStefano Zampini }
1376a3df083aSStefano Zampini 
1377a3df083aSStefano Zampini #undef __FUNCT__
1378a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1379a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1380a3df083aSStefano Zampini {
1381a3df083aSStefano Zampini   PetscErrorCode ierr;
1382a3df083aSStefano Zampini 
1383a3df083aSStefano Zampini   PetscFunctionBegin;
1384a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1385a3df083aSStefano Zampini   PetscFunctionReturn(0);
1386a3df083aSStefano Zampini }
1387a3df083aSStefano Zampini 
1388a3df083aSStefano Zampini #undef __FUNCT__
1389a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1390a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1391a3df083aSStefano Zampini {
1392a3df083aSStefano Zampini   PetscErrorCode ierr;
1393a3df083aSStefano Zampini 
1394a3df083aSStefano Zampini   PetscFunctionBegin;
1395a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1396a3df083aSStefano Zampini   PetscFunctionReturn(0);
1397a3df083aSStefano Zampini }
1398a3df083aSStefano Zampini 
1399a3df083aSStefano Zampini #undef __FUNCT__
1400a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1401a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1402a3df083aSStefano Zampini {
1403a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1404a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1405a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1406a3df083aSStefano Zampini   PetscErrorCode          ierr;
1407a3df083aSStefano Zampini 
1408a3df083aSStefano Zampini   PetscFunctionBegin;
1409a3df083aSStefano Zampini   if (!restore) {
14101dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1411a3df083aSStefano Zampini     PetscScalar        *work;
1412b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1413a3df083aSStefano Zampini 
14149a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
14159a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1416a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1417a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1418a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1419a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1420a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1421a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1422a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1423a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1424a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1425a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1426a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1427a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1428059032f7SStefano Zampini     if (reuse) {
1429a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
14301dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1431059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1432059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1433059032f7SStefano Zampini       PetscInt               i;
1434059032f7SStefano Zampini 
1435059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1436059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1437059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1438059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1439059032f7SStefano Zampini       }
1440059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
14411dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1442059032f7SStefano Zampini     }
1443a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1444a3df083aSStefano Zampini     ctx->work = work;
1445a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1446a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1447a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1448a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1449a3df083aSStefano Zampini 
1450a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1451a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1452a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1453a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1454a3df083aSStefano Zampini   } else {
14551dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
14561dd7afcfSStefano Zampini       PetscFunctionReturn(0);
14571dd7afcfSStefano Zampini     }
1458a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1459a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1460a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
14611dd7afcfSStefano Zampini     ctx->A = NULL;
14621dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
14631dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
14641dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
14651dd7afcfSStefano Zampini     if (ctx->free) {
1466059032f7SStefano Zampini       PetscInt i;
14671dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1468059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1469059032f7SStefano Zampini       }
1470059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1471059032f7SStefano Zampini     }
1472a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1473a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1474a3df083aSStefano Zampini   }
1475a3df083aSStefano Zampini   PetscFunctionReturn(0);
1476a3df083aSStefano Zampini }
1477a3df083aSStefano Zampini 
1478a3df083aSStefano Zampini /* used just in bddc debug mode */
1479a3df083aSStefano Zampini #undef __FUNCT__
1480a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1481a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1482a3df083aSStefano Zampini {
1483a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1484a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1485a3df083aSStefano Zampini   Mat            An;
1486a3df083aSStefano Zampini   PetscErrorCode ierr;
1487a3df083aSStefano Zampini 
1488a3df083aSStefano Zampini   PetscFunctionBegin;
1489a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1490a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1491a3df083aSStefano Zampini   if (is1) {
1492a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1493a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1494a3df083aSStefano Zampini   } else {
1495a3df083aSStefano Zampini     *B = An;
1496a3df083aSStefano Zampini   }
1497a3df083aSStefano Zampini   PetscFunctionReturn(0);
1498a3df083aSStefano Zampini }
1499a3df083aSStefano Zampini 
15001cf9b237SStefano Zampini /* TODO: add reuse flag */
15011cf9b237SStefano Zampini #undef __FUNCT__
15021cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
15031cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
15041cf9b237SStefano Zampini {
15051cf9b237SStefano Zampini   Mat            Bt;
15061cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
15071cf9b237SStefano Zampini   const PetscInt *ii,*ij;
15081cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
15091cf9b237SStefano Zampini   PetscBool      flg_row;
15101cf9b237SStefano Zampini   PetscErrorCode ierr;
15111cf9b237SStefano Zampini 
15121cf9b237SStefano Zampini   PetscFunctionBegin;
15131cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
15141cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15151cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
15161cf9b237SStefano Zampini   nnz = n;
15171cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
15181cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
15191cf9b237SStefano Zampini   }
15201cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
15211cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
15221cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
15231cf9b237SStefano Zampini   nnz = 0;
15241cf9b237SStefano Zampini   bii[0] = 0;
15251cf9b237SStefano Zampini   for (i=0;i<n;i++) {
15261cf9b237SStefano Zampini     PetscInt j;
15271cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
15281cf9b237SStefano Zampini       PetscScalar entry = a[j];
15291cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
15301cf9b237SStefano Zampini         bij[nnz] = ij[j];
15311cf9b237SStefano Zampini         bdata[nnz] = entry;
15321cf9b237SStefano Zampini         nnz++;
15331cf9b237SStefano Zampini       }
15341cf9b237SStefano Zampini     }
15351cf9b237SStefano Zampini     bii[i+1] = nnz;
15361cf9b237SStefano Zampini   }
15371cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
15381cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
15391cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
15401cf9b237SStefano Zampini   {
15411cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
15421cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
15431cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
15441cf9b237SStefano Zampini   }
15451cf9b237SStefano Zampini   *B = Bt;
15461cf9b237SStefano Zampini   PetscFunctionReturn(0);
15471cf9b237SStefano Zampini }
15481cf9b237SStefano Zampini 
1549674ae819SStefano Zampini #undef __FUNCT__
15504f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
15514f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
15524f1b2e48SStefano Zampini {
15534f1b2e48SStefano Zampini   Mat                    B;
15544f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
15554f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
15564f1b2e48SStefano Zampini   PCBDDCGraph            graph;
15574f1b2e48SStefano Zampini   PetscInt               i,n;
15584f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
15594f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
15604f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
15614f1b2e48SStefano Zampini   PetscErrorCode         ierr;
15624f1b2e48SStefano Zampini 
15634f1b2e48SStefano Zampini   PetscFunctionBegin;
156463c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
156563c961adSStefano Zampini     *ncc = 0;
156663c961adSStefano Zampini     *cc = NULL;
156763c961adSStefano Zampini     PetscFunctionReturn(0);
156863c961adSStefano Zampini   }
15694f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
15704f1b2e48SStefano Zampini   if (!isseqaij && filter) {
15711cf9b237SStefano Zampini     PetscBool isseqdense;
15721cf9b237SStefano Zampini 
15731cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
15741cf9b237SStefano Zampini     if (!isseqdense) {
15754f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
15761cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
15771cf9b237SStefano Zampini       PetscScalar *array;
15781cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
15791cf9b237SStefano Zampini 
15801cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
15811cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
15821cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
15831cf9b237SStefano Zampini       for (i=0;i<n;i++) {
15841cf9b237SStefano Zampini         PetscInt j;
15851cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
15861cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
15871cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
15881cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
15891cf9b237SStefano Zampini         }
15901cf9b237SStefano Zampini       }
15911cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
15929d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
15931cf9b237SStefano Zampini     }
15944f1b2e48SStefano Zampini   } else {
15954f1b2e48SStefano Zampini     B = A;
15964f1b2e48SStefano Zampini   }
15974f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
15984f1b2e48SStefano Zampini 
15994f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
16004f1b2e48SStefano Zampini   if (filter) {
16014f1b2e48SStefano Zampini     PetscScalar *data;
16024f1b2e48SStefano Zampini     PetscInt    j,cum;
16034f1b2e48SStefano Zampini 
16044f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
16054f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
16064f1b2e48SStefano Zampini     cum = 0;
16074f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
16084f1b2e48SStefano Zampini       PetscInt t;
16094f1b2e48SStefano Zampini 
16104f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
16114f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
16124f1b2e48SStefano Zampini           continue;
16134f1b2e48SStefano Zampini         }
16144f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
16154f1b2e48SStefano Zampini       }
16164f1b2e48SStefano Zampini       t = xadj_filtered[i];
16174f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
16184f1b2e48SStefano Zampini       cum += t;
16194f1b2e48SStefano Zampini     }
16204f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
16214f1b2e48SStefano Zampini   } else {
16224f1b2e48SStefano Zampini     xadj_filtered = NULL;
16234f1b2e48SStefano Zampini     adjncy_filtered = NULL;
16244f1b2e48SStefano Zampini   }
16254f1b2e48SStefano Zampini 
16264f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
16274f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
16284f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
16294f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
16304f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1631be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
16324f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
16334f1b2e48SStefano Zampini   if (xadj_filtered) {
16344f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
16354f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
16364f1b2e48SStefano Zampini   } else {
16374f1b2e48SStefano Zampini     graph->xadj = xadj;
16384f1b2e48SStefano Zampini     graph->adjncy = adjncy;
16394f1b2e48SStefano Zampini   }
16404f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
16414f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
16424f1b2e48SStefano Zampini   /* partial clean up */
16434f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
16444f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
16451cf9b237SStefano Zampini   if (A != B) {
16464f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
16474f1b2e48SStefano Zampini   }
16484f1b2e48SStefano Zampini 
16494f1b2e48SStefano Zampini   /* get back data */
16501cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
16511cf9b237SStefano Zampini   if (cc) {
16524f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
16534f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
16544f1b2e48SStefano 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);
16554f1b2e48SStefano Zampini     }
16564f1b2e48SStefano Zampini     *cc = cc_n;
16571cf9b237SStefano Zampini   }
16584f1b2e48SStefano Zampini   /* clean up graph */
16594f1b2e48SStefano Zampini   graph->xadj = 0;
16604f1b2e48SStefano Zampini   graph->adjncy = 0;
16614f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
16624f1b2e48SStefano Zampini   PetscFunctionReturn(0);
16634f1b2e48SStefano Zampini }
16644f1b2e48SStefano Zampini 
16654f1b2e48SStefano Zampini #undef __FUNCT__
16665408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
16675408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
16685408967cSStefano Zampini {
16695408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
16705408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1671dee84bffSStefano Zampini   IS             dirIS = NULL;
16724f1b2e48SStefano Zampini   PetscInt       i;
16735408967cSStefano Zampini   PetscErrorCode ierr;
16745408967cSStefano Zampini 
16755408967cSStefano Zampini   PetscFunctionBegin;
1676dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
16775408967cSStefano Zampini   if (zerodiag) {
16785408967cSStefano Zampini     Mat            A;
16795408967cSStefano Zampini     Vec            vec3_N;
16805408967cSStefano Zampini     PetscScalar    *vals;
16815408967cSStefano Zampini     const PetscInt *idxs;
1682d12d3064SStefano Zampini     PetscInt       nz,*count;
16835408967cSStefano Zampini 
16845408967cSStefano Zampini     /* p0 */
16855408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
16865408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
16875408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
16885408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
16894f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
16905408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
16915408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
16925408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
16935408967cSStefano Zampini     /* v_I */
16945408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
16955408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
16965408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
16975408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
16985408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
16995408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
17005408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17015408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
17025408967cSStefano Zampini     if (dirIS) {
17035408967cSStefano Zampini       PetscInt n;
17045408967cSStefano Zampini 
17055408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
17065408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
17075408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
17085408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
17095408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
17105408967cSStefano Zampini     }
17115408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
17125408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
17135408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
17145408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1715669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
17165408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
17175408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
17189a962809SStefano 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]));
17195408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
17205408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1721d12d3064SStefano Zampini 
1722d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1723d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1724d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1725d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1726d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1727d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
17289a962809SStefano 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]);
1729d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1730d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
17315408967cSStefano Zampini   }
1732dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
17335408967cSStefano Zampini 
17345408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
17355408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
17364f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
17375408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
17384f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
17395408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1740f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1741f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1742f2a566d8SStefano 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);
1743f2a566d8SStefano Zampini   }
17445408967cSStefano Zampini   PetscFunctionReturn(0);
17455408967cSStefano Zampini }
17465408967cSStefano Zampini 
17475408967cSStefano Zampini #undef __FUNCT__
1748339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1749339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1750339f8db1SStefano Zampini {
1751339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17524f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1753b0f5fe93SStefano Zampini   PetscInt       nz,n;
17541f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
17554f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1756339f8db1SStefano Zampini   PetscErrorCode ierr;
1757339f8db1SStefano Zampini 
1758339f8db1SStefano Zampini   PetscFunctionBegin;
17599f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
17609f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1761a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1762a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1763a3df083aSStefano Zampini   }
1764a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1765a3df083aSStefano Zampini   pcbddc->benign_n = 0;
17661ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
17674f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
17684f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
17694f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
17701ae86dd6SStefano Zampini      since the local Schur complements are already SPD
17714f1b2e48SStefano Zampini   */
17724f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
17734f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
177440fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
17754f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
17764f1b2e48SStefano Zampini 
17774f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
17784f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
17794f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
17804f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1781ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
178240fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
178340fa8d13SStefano Zampini     if (!sorted) {
178440fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
178540fa8d13SStefano Zampini     }
178640fa8d13SStefano Zampini   } else {
178740fa8d13SStefano Zampini     pressures = NULL;
178840fa8d13SStefano Zampini   }
178997d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
179097d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
179127b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
179297d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1793339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1794339f8db1SStefano Zampini   if (!sorted) {
1795339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1796339f8db1SStefano Zampini   }
1797339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17984f1b2e48SStefano Zampini   if (!nz) {
17994f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
18004f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
180140fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
180240fa8d13SStefano Zampini   }
18034f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
18044f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
18054f1b2e48SStefano Zampini   zerodiag_subs = NULL;
18064f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
18071f4df5f7SStefano Zampini   n_interior_dofs = 0;
18081f4df5f7SStefano Zampini   interior_dofs = NULL;
18091f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
18101f4df5f7SStefano Zampini     PetscInt n,i,j;
18111f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
18121f4df5f7SStefano Zampini     PetscInt *iwork;
18131f4df5f7SStefano Zampini 
18141f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
18151f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18161f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
18171f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
181890648384SStefano Zampini     for (i=1;i<n_neigh;i++)
18191f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
18201f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
18211f4df5f7SStefano Zampini     for (i=0;i<n;i++)
18221f4df5f7SStefano Zampini       if (!iwork[i])
18231f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
18241f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
18251f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
18261f4df5f7SStefano Zampini   }
18274f1b2e48SStefano Zampini   if (has_null_pressures) {
18284f1b2e48SStefano Zampini     IS             *subs;
18291f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
18301f4df5f7SStefano Zampini     const PetscInt *idxs;
18311f4df5f7SStefano Zampini     PetscScalar    *array;
18321f4df5f7SStefano Zampini     Vec            *work;
18331f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
18344f1b2e48SStefano Zampini 
18354f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
18364f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
18371f4df5f7SStefano 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) */
18381f4df5f7SStefano Zampini     if (pcbddc->current_level) {
18391f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
18401f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
18411f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
18421f4df5f7SStefano Zampini       /* work[0] = 1_p */
18431f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
18441f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
18451f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
18461f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
18471f4df5f7SStefano Zampini       /* work[0] = 1_v */
18481f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
18491f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
18501f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
18511f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
18521f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
18531f4df5f7SStefano Zampini     }
18544f1b2e48SStefano Zampini     if (nsubs > 1) {
18554f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
18564f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
18574f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
18584f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
18594f1b2e48SStefano Zampini         PetscInt               nl;
18604f1b2e48SStefano Zampini 
18614f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
18624f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
18634f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
18644f1b2e48SStefano Zampini         if (nl) {
18654f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
18664f1b2e48SStefano Zampini 
18671f4df5f7SStefano Zampini           if (pcbddc->current_level) {
18681f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
18691f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
18701f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
18711f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
18721f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
18731f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
18741f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
18751f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
18761f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
18771f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
18781f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
18791f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
18801f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
18811f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
18821f4df5f7SStefano Zampini                 break;
18831f4df5f7SStefano Zampini               }
18841f4df5f7SStefano Zampini             }
18851f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
18861f4df5f7SStefano Zampini           }
18871f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
18881f4df5f7SStefano Zampini             IS       t_bc;
18891f4df5f7SStefano Zampini             PetscInt nzb;
18901f4df5f7SStefano Zampini 
18911f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
18921f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
18931f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
18941f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
18951f4df5f7SStefano Zampini           }
18961f4df5f7SStefano Zampini           if (valid && pressures) {
18974f1b2e48SStefano Zampini             IS t_pressure_subs;
18984f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
18994f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
19004f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
19014f1b2e48SStefano Zampini           }
19024f1b2e48SStefano Zampini           if (valid) {
19034f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
19044f1b2e48SStefano Zampini             pcbddc->benign_n++;
19054f1b2e48SStefano Zampini           } else {
19064f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
19074f1b2e48SStefano Zampini           }
19084f1b2e48SStefano Zampini         }
19094f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
19104f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
19114f1b2e48SStefano Zampini       }
19124f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
19134f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
19141f4df5f7SStefano Zampini 
19151f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
19161f4df5f7SStefano Zampini         PetscInt nzb;
19171f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
19181f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
19191f4df5f7SStefano Zampini       }
19201f4df5f7SStefano Zampini       if (valid && pressures) {
19214f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
19224f1b2e48SStefano Zampini       }
19231f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
19241f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
19251f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
19261f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
19271f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
19281f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
19291f4df5f7SStefano Zampini               valid = PETSC_FALSE;
19301f4df5f7SStefano Zampini               break;
19311f4df5f7SStefano Zampini           }
19321f4df5f7SStefano Zampini         }
19331f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
19341f4df5f7SStefano Zampini       }
19354f1b2e48SStefano Zampini       if (valid) {
19364f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1937ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
19384f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
19394f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
19404f1b2e48SStefano Zampini       }
19414f1b2e48SStefano Zampini     }
19421f4df5f7SStefano Zampini     if (pcbddc->current_level) {
19431f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
19444f1b2e48SStefano Zampini     }
19451f4df5f7SStefano Zampini   }
19461f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
19474f1b2e48SStefano Zampini 
19484f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1949b9b0e38cSStefano Zampini     PetscInt n;
1950b9b0e38cSStefano Zampini 
19514f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
19524f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1953b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1954b9b0e38cSStefano Zampini     if (n) {
19554f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
19564f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
19574f1b2e48SStefano Zampini     }
1958b9b0e38cSStefano Zampini   }
19594f1b2e48SStefano Zampini 
19604f1b2e48SStefano Zampini   /* final check for null pressures */
19614f1b2e48SStefano Zampini   if (zerodiag && pressures) {
19624f1b2e48SStefano Zampini     PetscInt nz,np;
19634f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
19644f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
19654f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
19664f1b2e48SStefano Zampini   }
19674f1b2e48SStefano Zampini 
19684f1b2e48SStefano Zampini   if (recompute_zerodiag) {
19694f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
19704f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
19714f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
19724f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
19734f1b2e48SStefano Zampini     } else {
19744f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
19754f1b2e48SStefano Zampini 
19764f1b2e48SStefano Zampini       nzn = 0;
19774f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
19784f1b2e48SStefano Zampini         PetscInt ns;
19794f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
19804f1b2e48SStefano Zampini         nzn += ns;
19814f1b2e48SStefano Zampini       }
19824f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
19834f1b2e48SStefano Zampini       nzn = 0;
19844f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
19854f1b2e48SStefano Zampini         PetscInt ns,*idxs;
19864f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
19874f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
19884f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
19894f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
19904f1b2e48SStefano Zampini         nzn += ns;
19914f1b2e48SStefano Zampini       }
19924f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
19934f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
19944f1b2e48SStefano Zampini     }
19954f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
19964f1b2e48SStefano Zampini   }
19974f1b2e48SStefano Zampini 
1998669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
1999a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
2000a198735bSStefano Zampini     Mat                    A,loc_divudotp;
2001a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
2002a198735bSStefano Zampini     IS                     row,col,isused = NULL;
2003a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
2004a198735bSStefano Zampini 
20051f4df5f7SStefano Zampini     if (pressures) {
20061f4df5f7SStefano Zampini       isused = pressures;
20071f4df5f7SStefano Zampini     } else {
20081f4df5f7SStefano Zampini       isused = zerodiag;
20091f4df5f7SStefano Zampini     }
2010a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
2011669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
20121ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
20131ae86dd6SStefano 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");
2014a198735bSStefano Zampini     n_isused = 0;
2015a198735bSStefano Zampini     if (isused) {
2016a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
2017a198735bSStefano Zampini     }
2018a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2019a198735bSStefano Zampini     st = st-n_isused;
20201ae86dd6SStefano Zampini     if (n) {
2021a198735bSStefano Zampini       const PetscInt *gidxs;
2022a198735bSStefano Zampini 
2023a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
2024a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
2025a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
2026a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2027a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2028a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
20291ae86dd6SStefano Zampini     } else {
2030a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
2031a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
2032a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
2033a198735bSStefano Zampini     }
2034a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
2035a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
2036a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
2037a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
2038a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
2039a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
2040a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
2041a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
2042a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2043a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
2044a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2045a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2046a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
2047a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
20481ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20491ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20501ae86dd6SStefano Zampini   }
2051b3afcdbeSStefano Zampini 
2052b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
20534f1b2e48SStefano Zampini   if (has_null_pressures) {
20544f1b2e48SStefano Zampini     IS             zerodiagc;
20554f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
20564f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
20574f1b2e48SStefano Zampini 
20584f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2059339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
2060339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
2061339f8db1SStefano Zampini     /* local change of basis for pressures */
2062339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
206397d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
2064339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
2065339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2066339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
20674f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
20684f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
20694f1b2e48SStefano Zampini       PetscInt nzs,j;
20704f1b2e48SStefano Zampini 
20714f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
20724f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
20734f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
20744f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
20754f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
20764f1b2e48SStefano Zampini     }
2077339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
2078339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2079339f8db1SStefano Zampini     /* set identity on velocities */
2080339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
2081339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
2082339f8db1SStefano Zampini     }
20834f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
20844f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
20859f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
20864f1b2e48SStefano 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);
2087339f8db1SStefano Zampini     /* set change on pressures */
20884f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
20894f1b2e48SStefano Zampini       PetscScalar *array;
20904f1b2e48SStefano Zampini       PetscInt    nzs;
20914f1b2e48SStefano Zampini 
20924f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
20934f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
20944f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
2095339f8db1SStefano Zampini         PetscScalar vals[2];
2096339f8db1SStefano Zampini         PetscInt    cols[2];
2097339f8db1SStefano Zampini 
2098339f8db1SStefano Zampini         cols[0] = idxs[i];
20994f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
2100339f8db1SStefano Zampini         vals[0] = 1.;
2101b0f5fe93SStefano Zampini         vals[1] = 1.;
21024f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
2103339f8db1SStefano Zampini       }
21044f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
21054f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
21064f1b2e48SStefano Zampini       array[nzs-1] = 1.;
21074f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
21084f1b2e48SStefano Zampini       /* store local idxs for p0 */
21094f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
21104f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
2111339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
21124f1b2e48SStefano Zampini     }
2113339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2114339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2115a3df083aSStefano Zampini     /* project if needed */
2116a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
21171dd7afcfSStefano Zampini       Mat M;
21181dd7afcfSStefano Zampini 
21191dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2120339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
21211dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
21221dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
2123a3df083aSStefano Zampini     }
21244f1b2e48SStefano Zampini     /* store global idxs for p0 */
21254f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2126339f8db1SStefano Zampini   }
2127ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
21284f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
2129b0f5fe93SStefano Zampini 
2130b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
2131b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
213227b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
213327b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2134339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
2135339f8db1SStefano Zampini   PetscFunctionReturn(0);
2136339f8db1SStefano Zampini }
2137339f8db1SStefano Zampini 
2138339f8db1SStefano Zampini #undef __FUNCT__
2139015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
2140015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
2141efc2fbd9SStefano Zampini {
2142efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2143de9d7bd0SStefano Zampini   PetscScalar    *array;
2144efc2fbd9SStefano Zampini   PetscErrorCode ierr;
2145efc2fbd9SStefano Zampini 
2146efc2fbd9SStefano Zampini   PetscFunctionBegin;
2147efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
2148efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
21494f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
2150efc2fbd9SStefano Zampini   }
2151de9d7bd0SStefano Zampini   if (get) {
2152efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
21534f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
21544f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
2155efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
2156de9d7bd0SStefano Zampini   } else {
2157de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
2158de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2159de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
2160de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
2161efc2fbd9SStefano Zampini   }
2162efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
2163efc2fbd9SStefano Zampini }
2164efc2fbd9SStefano Zampini 
2165efc2fbd9SStefano Zampini #undef __FUNCT__
2166c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
2167c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
2168c263805aSStefano Zampini {
2169c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2170c263805aSStefano Zampini   PetscErrorCode ierr;
2171c263805aSStefano Zampini 
2172c263805aSStefano Zampini   PetscFunctionBegin;
2173c263805aSStefano Zampini   /* TODO: add error checking
2174c263805aSStefano Zampini     - avoid nested pop (or push) calls.
2175c263805aSStefano Zampini     - cannot push before pop.
21761c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2177c263805aSStefano Zampini   */
21784f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2179efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2180efc2fbd9SStefano Zampini   }
2181c263805aSStefano Zampini   if (pop) {
2182a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
21834f1b2e48SStefano Zampini       IS       is_p0;
21844f1b2e48SStefano Zampini       MatReuse reuse;
2185c263805aSStefano Zampini 
2186c263805aSStefano Zampini       /* extract B_0 */
21874f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
21884f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
21894f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
21904f1b2e48SStefano Zampini       }
21914f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
21924f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2193c263805aSStefano Zampini       /* remove rows and cols from local problem */
2194c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
219597d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
21964f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
21974f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2198a3df083aSStefano Zampini     } else {
2199a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2200a3df083aSStefano Zampini       PetscScalar *vals;
2201a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2202a3df083aSStefano Zampini 
2203a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2204a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2205a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
22060b5adadeSStefano Zampini         PetscInt *nnz;
2207a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2208a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2209a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2210331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2211331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2212331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2213331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2214331e053bSStefano Zampini         }
2215331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2216331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2217331e053bSStefano Zampini       }
2218a3df083aSStefano Zampini 
2219a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2220a3df083aSStefano Zampini         PetscScalar *array;
2221a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2222a3df083aSStefano Zampini 
2223a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2224a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2225a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2226a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2227a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2228a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2229a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2230a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2231a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2232a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2233a3df083aSStefano Zampini         cum = 0;
2234a3df083aSStefano Zampini         for (j=0;j<n;j++) {
223522db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2236a3df083aSStefano Zampini             vals[cum] = array[j];
2237a3df083aSStefano Zampini             idxs_ins[cum] = j;
2238a3df083aSStefano Zampini             cum++;
2239a3df083aSStefano Zampini           }
2240a3df083aSStefano Zampini         }
2241a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2242a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2243a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2244a3df083aSStefano Zampini       }
2245a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2246a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2247a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2248a3df083aSStefano Zampini     }
2249c263805aSStefano Zampini   } else { /* push */
2250a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
22514f1b2e48SStefano Zampini       PetscInt i;
22524f1b2e48SStefano Zampini 
22534f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
22544f1b2e48SStefano Zampini         PetscScalar *B0_vals;
22554f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
22564f1b2e48SStefano Zampini 
22574f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22584f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
22597b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
22604f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
22614f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
22624f1b2e48SStefano Zampini       }
2263c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2264c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2265a3df083aSStefano Zampini     } else {
2266a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2267a3df083aSStefano Zampini     }
2268c263805aSStefano Zampini   }
2269c263805aSStefano Zampini   PetscFunctionReturn(0);
2270c263805aSStefano Zampini }
2271c263805aSStefano Zampini 
2272c263805aSStefano Zampini #undef __FUNCT__
2273b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
227408122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2275b1b3d7a2SStefano Zampini {
2276b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
227708122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
227808122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
227908122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
228008122e43SStefano Zampini   PetscScalar     *work,lwork;
228108122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
228208122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
228308122e43SStefano Zampini   PetscReal       *eigs,thresh;
22841b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2285f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
228608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
228708122e43SStefano Zampini   PetscReal       *rwork;
228808122e43SStefano Zampini #endif
2289b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2290b1b3d7a2SStefano Zampini 
2291b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2292b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2293af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2294af25d912SStefano 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);
229506a4e24aSStefano Zampini 
2296fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2297fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2298fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2299fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
23001575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2301fd14bc51SStefano Zampini   }
2302fd14bc51SStefano Zampini 
2303e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2304e496cd5dSStefano 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);
2305e496cd5dSStefano Zampini   }
2306e496cd5dSStefano Zampini 
230708122e43SStefano Zampini   /* max size of subsets */
230808122e43SStefano Zampini   mss = 0;
230908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
231008122e43SStefano Zampini     PetscInt subset_size;
2311862806e4SStefano Zampini 
231208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
231308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
231408122e43SStefano Zampini   }
231508122e43SStefano Zampini 
231608122e43SStefano Zampini   /* min/max and threshold */
231708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2318f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
231908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2320f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2321f6f667cfSStefano Zampini   if (nmin) {
2322f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2323f6f667cfSStefano Zampini   }
232408122e43SStefano Zampini 
232508122e43SStefano Zampini   /* allocate lapack workspace */
232608122e43SStefano Zampini   cum = cum2 = 0;
232708122e43SStefano Zampini   maxneigs = 0;
232808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
232908122e43SStefano Zampini     PetscInt n,subset_size;
2330f6f667cfSStefano Zampini 
233108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
233208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
23339162d606SStefano Zampini     cum += subset_size;
23349162d606SStefano Zampini     cum2 += subset_size*n;
233508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
233608122e43SStefano Zampini   }
233708122e43SStefano Zampini   if (mss) {
23389ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
233908122e43SStefano Zampini       PetscBLASInt B_itype = 1;
234008122e43SStefano Zampini       PetscBLASInt B_N = mss;
23414c6709b3SStefano Zampini       PetscReal    zero = 0.0;
23424c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
234308122e43SStefano Zampini 
234408122e43SStefano Zampini       B_lwork = -1;
234508122e43SStefano Zampini       S = NULL;
234608122e43SStefano Zampini       St = NULL;
2347a58a30b4SStefano Zampini       eigs = NULL;
2348a58a30b4SStefano Zampini       eigv = NULL;
2349a58a30b4SStefano Zampini       B_iwork = NULL;
2350a58a30b4SStefano Zampini       B_ifail = NULL;
2351d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2352d1710679SStefano Zampini       rwork = NULL;
2353d1710679SStefano Zampini #endif
23548bec7fa6SStefano Zampini       thresh = 1.0;
235508122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
235608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
235708122e43SStefano 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));
235808122e43SStefano Zampini #else
235908122e43SStefano 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));
236008122e43SStefano Zampini #endif
236108122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
236208122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
236308122e43SStefano Zampini     } else {
236408122e43SStefano Zampini         /* TODO */
236508122e43SStefano Zampini     }
236608122e43SStefano Zampini   } else {
236708122e43SStefano Zampini     lwork = 0;
236808122e43SStefano Zampini   }
236908122e43SStefano Zampini 
237008122e43SStefano Zampini   nv = 0;
2371d62866d3SStefano 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) */
2372d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
237308122e43SStefano Zampini   }
23744c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2375f6f667cfSStefano Zampini   if (allocated_S_St) {
2376f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2377f6f667cfSStefano Zampini   }
2378f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
237908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
238008122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
238108122e43SStefano Zampini #endif
23829162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
23839162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
23849162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
238508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
23869162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
238708122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
238808122e43SStefano Zampini 
238908122e43SStefano Zampini   maxneigs = 0;
239072b8c272SStefano Zampini   cum = cumarray = 0;
23919162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
23929162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2393d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
239408122e43SStefano Zampini     const PetscInt *idxs;
239508122e43SStefano Zampini 
2396d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
239708122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
239808122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
239908122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
240008122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
24019162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
24029162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
240308122e43SStefano Zampini     }
2404d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
240508122e43SStefano Zampini   }
240608122e43SStefano Zampini 
240708122e43SStefano Zampini   if (mss) { /* multilevel */
240808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
240908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
241008122e43SStefano Zampini   }
241108122e43SStefano Zampini 
2412ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
241308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
241408122e43SStefano Zampini     const PetscInt *idxs;
24159d54b7f4SStefano Zampini     PetscReal      upper,lower;
2416862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
241708122e43SStefano Zampini     PetscBLASInt   B_N;
2418aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
241908122e43SStefano Zampini 
24209d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
24219d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
24229d54b7f4SStefano Zampini       lower = thresh;
24239d54b7f4SStefano Zampini     } else {
24249d54b7f4SStefano Zampini       upper = 1./thresh;
24259d54b7f4SStefano Zampini       lower = 0.;
24269d54b7f4SStefano Zampini     }
2427862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2428ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2429f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2430f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
24319ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2432aff50787SStefano Zampini         PetscInt j,k;
2433aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2434aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2435aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
243608122e43SStefano Zampini         }
243708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2438aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2439aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2440aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2441aff50787SStefano Zampini           }
244208122e43SStefano Zampini         }
244308122e43SStefano Zampini       } else {
244408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
244508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
244608122e43SStefano Zampini       }
24478bec7fa6SStefano Zampini     } else {
2448f6f667cfSStefano Zampini       S = Sarray + cumarray;
2449f6f667cfSStefano Zampini       St = Starray + cumarray;
24508bec7fa6SStefano Zampini     }
2451aff50787SStefano Zampini     /* see if we can save some work */
2452b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2453aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2454aff50787SStefano Zampini     }
2455aff50787SStefano Zampini 
2456b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2457aff50787SStefano Zampini       B_neigs = 0;
2458aff50787SStefano Zampini     } else {
24599ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
246008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2461f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
24624c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
24639552c7c7SStefano Zampini         PetscInt     nmin_s;
2464b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
246508122e43SStefano Zampini 
2466fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
24678bec7fa6SStefano 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]]);
2468fd14bc51SStefano Zampini         }
2469d16cbb6bSStefano Zampini 
2470b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2471b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2472b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2473b7ab4a40SStefano Zampini         }
2474b7ab4a40SStefano Zampini 
247508122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2476b7ab4a40SStefano Zampini         if (compute_range) {
2477d16cbb6bSStefano Zampini 
2478d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
247908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
24809d54b7f4SStefano 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));
248108122e43SStefano Zampini #else
24829d54b7f4SStefano 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));
248308122e43SStefano Zampini #endif
2484b7ab4a40SStefano Zampini         } else if (!same_data) {
2485d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2486d16cbb6bSStefano Zampini           B_IL = 1;
2487d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
24889d54b7f4SStefano 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));
2489d16cbb6bSStefano Zampini #else
24909d54b7f4SStefano 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));
2491d16cbb6bSStefano Zampini #endif
2492b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2493b7ab4a40SStefano Zampini           PetscInt k;
2494b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2495b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2496b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2497b7ab4a40SStefano Zampini           nmin = nmax;
2498b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2499b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2500b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2501b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2502b7ab4a40SStefano Zampini           }
2503d16cbb6bSStefano Zampini         }
250408122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
250508122e43SStefano Zampini         if (B_ierr) {
25066c4ed002SBarry 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);
25076c4ed002SBarry 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);
25086c4ed002SBarry 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);
250908122e43SStefano Zampini         }
251008122e43SStefano Zampini 
251108122e43SStefano Zampini         if (B_neigs > nmax) {
2512fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2513fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2514fd14bc51SStefano Zampini           }
25159d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
251608122e43SStefano Zampini           B_neigs = nmax;
251708122e43SStefano Zampini         }
251808122e43SStefano Zampini 
25199552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
25209552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
252108122e43SStefano Zampini           PetscBLASInt B_neigs2;
252208122e43SStefano Zampini 
25239d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2524f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
25259d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
25269d54b7f4SStefano Zampini           } else {
25279d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
25289d54b7f4SStefano Zampini             B_IU = nmin_s;
25299d54b7f4SStefano Zampini           }
2530fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2531fd14bc51SStefano 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);
2532fd14bc51SStefano Zampini           }
25339ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
25341ae86dd6SStefano Zampini             PetscInt j,k;
253508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
25361ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
25371ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
25381ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
253908122e43SStefano Zampini               }
254008122e43SStefano Zampini             }
254108122e43SStefano Zampini           } else {
254208122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
254308122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
254408122e43SStefano Zampini           }
254508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
254608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
25479d54b7f4SStefano 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));
254808122e43SStefano Zampini #else
25499d54b7f4SStefano 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));
255008122e43SStefano Zampini #endif
255108122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
255208122e43SStefano Zampini           B_neigs += B_neigs2;
255308122e43SStefano Zampini         }
255408122e43SStefano Zampini         if (B_ierr) {
25556c4ed002SBarry 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);
25566c4ed002SBarry 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);
25576c4ed002SBarry 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);
255808122e43SStefano Zampini         }
2559fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2560ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
256108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
256208122e43SStefano Zampini             if (eigs[j] == 0.0) {
2563ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
256408122e43SStefano Zampini             } else {
25659d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2566ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
25679d54b7f4SStefano Zampini               } else {
25689d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
25699d54b7f4SStefano Zampini               }
2570fd14bc51SStefano Zampini             }
257108122e43SStefano Zampini           }
257208122e43SStefano Zampini         }
257308122e43SStefano Zampini       } else {
257408122e43SStefano Zampini           /* TODO */
257508122e43SStefano Zampini       }
2576aff50787SStefano Zampini     }
25776c3e6151SStefano Zampini     /* change the basis back to the original one */
25786c3e6151SStefano Zampini     if (sub_schurs->change) {
257972b8c272SStefano Zampini       Mat change,phi,phit;
25806c3e6151SStefano Zampini 
25816c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
25826c3e6151SStefano Zampini         PetscInt ii;
25836c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
25846c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
25856c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2586684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2587684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2588684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2589684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2590684229deSStefano Zampini #else
25916c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2592684229deSStefano Zampini #endif
25936c3e6151SStefano Zampini           }
25946c3e6151SStefano Zampini         }
25956c3e6151SStefano Zampini       }
259672b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
25976c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
259872b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
25996c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
26006c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
26016c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
26026c3e6151SStefano Zampini     }
26038bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
26048bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
26059162d606SStefano Zampini     if (B_neigs) {
26069162d606SStefano 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);
2607fd14bc51SStefano Zampini 
2608fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
26099552c7c7SStefano Zampini         PetscInt ii;
26109552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2611ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
26129552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2613ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2614ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2615ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2616ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2617ac47001eSStefano Zampini #else
2618ac47001eSStefano 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);
2619ac47001eSStefano Zampini #endif
26209552c7c7SStefano Zampini           }
26219552c7c7SStefano Zampini         }
2622fd14bc51SStefano Zampini       }
26239162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
26249162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
26259162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
26269162d606SStefano Zampini       cum++;
262708122e43SStefano Zampini     }
262808122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
262908122e43SStefano Zampini     /* shift for next computation */
263008122e43SStefano Zampini     cumarray += subset_size*subset_size;
263108122e43SStefano Zampini   }
2632fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2633fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2634fd14bc51SStefano Zampini   }
263508122e43SStefano Zampini 
263608122e43SStefano Zampini   if (mss) {
263708122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
263808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2639f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2640f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2641f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
264208122e43SStefano Zampini   }
2643f6f667cfSStefano Zampini   if (allocated_S_St) {
2644f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2645f6f667cfSStefano Zampini   }
2646f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
264708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
264808122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
264908122e43SStefano Zampini #endif
265008122e43SStefano Zampini   if (pcbddc->dbg_flag) {
26511b968477SStefano Zampini     PetscInt maxneigs_r;
2652b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
26539b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
265408122e43SStefano Zampini   }
265508122e43SStefano Zampini   PetscFunctionReturn(0);
265608122e43SStefano Zampini }
2657b1b3d7a2SStefano Zampini 
2658674ae819SStefano Zampini #undef __FUNCT__
2659c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2660c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2661c8587f34SStefano Zampini {
26628629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2663c8587f34SStefano Zampini   PetscErrorCode ierr;
2664c8587f34SStefano Zampini 
2665c8587f34SStefano Zampini   PetscFunctionBegin;
2666f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
26675e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2668c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2669c8587f34SStefano Zampini 
2670684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
26710fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2672684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2673c8587f34SStefano Zampini 
26748629588bSStefano Zampini   /*
26758629588bSStefano Zampini      Setup local correction and local part of coarse basis.
26768629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
26778629588bSStefano Zampini   */
267847f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
26798629588bSStefano Zampini 
26808629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
26818629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
26828629588bSStefano Zampini 
26838629588bSStefano Zampini   /* free */
26848629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2685c8587f34SStefano Zampini   PetscFunctionReturn(0);
2686c8587f34SStefano Zampini }
2687c8587f34SStefano Zampini 
2688c8587f34SStefano Zampini #undef __FUNCT__
2689674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2690674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2691674ae819SStefano Zampini {
2692674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2693674ae819SStefano Zampini   PetscErrorCode ierr;
2694674ae819SStefano Zampini 
2695674ae819SStefano Zampini   PetscFunctionBegin;
2696674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
269730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2698674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2699785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2700674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2701f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2702f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2703785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
270463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
270563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2706674ae819SStefano Zampini   PetscFunctionReturn(0);
2707674ae819SStefano Zampini }
2708674ae819SStefano Zampini 
2709674ae819SStefano Zampini #undef __FUNCT__
2710674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2711674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2712674ae819SStefano Zampini {
2713674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
27144f1b2e48SStefano Zampini   PetscInt       i;
2715674ae819SStefano Zampini   PetscErrorCode ierr;
2716674ae819SStefano Zampini 
2717674ae819SStefano Zampini   PetscFunctionBegin;
2718a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2719b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2720674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
272116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
27221dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2723674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2724669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2725fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2726a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2727674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
272871582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_FALSE;
27294f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
27304f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
27314f1b2e48SStefano Zampini   }
27324f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2733b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2734b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2735b334f244SStefano Zampini   }
2736674ae819SStefano Zampini   PetscFunctionReturn(0);
2737674ae819SStefano Zampini }
2738674ae819SStefano Zampini 
2739674ae819SStefano Zampini #undef __FUNCT__
2740674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2741674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2742674ae819SStefano Zampini {
2743674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2744674ae819SStefano Zampini   PetscErrorCode ierr;
2745674ae819SStefano Zampini 
2746674ae819SStefano Zampini   PetscFunctionBegin;
2747674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
274858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2749ca92afb2SStefano Zampini     PetscScalar *array;
275006656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
275106656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
275258da7f69SStefano Zampini   }
2753674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2754674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
275515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
275615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2757674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2758674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2759674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
276006656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2761674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2762674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
27638ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2764674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2765674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2766674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2767f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2768f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2769f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2770f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2771727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
27720e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2773f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
277470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
277581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
27760369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
27771dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
27784f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
27798b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2780ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2781ca92afb2SStefano Zampini     PetscInt i;
2782ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2783ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2784ca92afb2SStefano Zampini     }
2785ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2786ca92afb2SStefano Zampini   }
27874f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2788674ae819SStefano Zampini   PetscFunctionReturn(0);
2789674ae819SStefano Zampini }
2790674ae819SStefano Zampini 
2791674ae819SStefano Zampini #undef __FUNCT__
2792f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2793f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
27946bfb1811SStefano Zampini {
27956bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
27966bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
27976bfb1811SStefano Zampini   VecType        impVecType;
27984f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
27996bfb1811SStefano Zampini   PetscErrorCode ierr;
28006bfb1811SStefano Zampini 
28016bfb1811SStefano Zampini   PetscFunctionBegin;
28026c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2803e7b262bdSStefano Zampini   /* get sizes */
28044f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2805b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
28066bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2807e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2808e7b262bdSStefano Zampini   /* R nodes */
2809e7b262bdSStefano Zampini   old_size = -1;
2810e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2811e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2812e7b262bdSStefano Zampini   }
2813e7b262bdSStefano Zampini   if (n_R != old_size) {
2814e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2815e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
28166bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
28176bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
28186bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
28196bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2820e7b262bdSStefano Zampini   }
2821e7b262bdSStefano Zampini   /* local primal dofs */
2822e7b262bdSStefano Zampini   old_size = -1;
2823e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2824e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2825e7b262bdSStefano Zampini   }
2826e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2827e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
282883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2829e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
28306bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2831e7b262bdSStefano Zampini   }
2832e7b262bdSStefano Zampini   /* local explicit constraints */
2833e7b262bdSStefano Zampini   old_size = -1;
2834e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2835e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2836e7b262bdSStefano Zampini   }
2837e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2838e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
283983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
284083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
284183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
284283b7ccabSStefano Zampini   }
28436bfb1811SStefano Zampini   PetscFunctionReturn(0);
28446bfb1811SStefano Zampini }
28456bfb1811SStefano Zampini 
28466bfb1811SStefano Zampini #undef __FUNCT__
284747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
284847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
284988ebb749SStefano Zampini {
285025084f0cSStefano Zampini   PetscErrorCode  ierr;
285125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
285288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
285388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2854d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
285525084f0cSStefano Zampini   /* submatrices of local problem */
285680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
285706656605SStefano Zampini   /* submatrices of local coarse problem */
285806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
285925084f0cSStefano Zampini   /* working matrices */
286006656605SStefano Zampini   Mat             C_CR;
286125084f0cSStefano Zampini   /* additional working stuff */
286206656605SStefano Zampini   PC              pc_R;
28634f1b2e48SStefano Zampini   Mat             F;
28645cbda25cSStefano Zampini   Vec             dummy_vec;
2865a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
286625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
286706656605SStefano Zampini   PetscScalar     *work;
286806656605SStefano Zampini   PetscInt        *idx_V_B;
2869ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
287006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2871ffd830a3SStefano Zampini 
287225084f0cSStefano Zampini   /* some shortcuts to scalars */
287306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
287488ebb749SStefano Zampini 
287588ebb749SStefano Zampini   PetscFunctionBegin;
28769a962809SStefano 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");
2877ffd830a3SStefano Zampini 
2878ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2879b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
28804f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2881b371cd4fSStefano Zampini   n_B = pcis->n_B;
2882b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
288388ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
288488ebb749SStefano Zampini 
288588ebb749SStefano Zampini   /* vertices in boundary numbering */
2886785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
28870e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
28886c4ed002SBarry 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);
288988ebb749SStefano Zampini 
289006656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2891019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
289206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
289306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
289406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
289506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
289606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
289706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
289806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
289906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
290006656605SStefano Zampini 
290106656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
290206656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
290306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
290406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
290506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2906ffd830a3SStefano Zampini   lda_rhs = n_R;
2907a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
290806656605SStefano Zampini   if (isLU || isILU || isCHOL) {
290906656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2910b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2911df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2912d62866d3SStefano Zampini     MatFactorType      type;
2913d62866d3SStefano Zampini 
2914df4d28bfSStefano Zampini     F = reuse_solver->F;
29156816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2916d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2917ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
291822db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
291906656605SStefano Zampini   } else {
292006656605SStefano Zampini     F = NULL;
292106656605SStefano Zampini   }
292206656605SStefano Zampini 
2923ffd830a3SStefano Zampini   /* allocate workspace */
2924ffd830a3SStefano Zampini   n = 0;
2925ffd830a3SStefano Zampini   if (n_constraints) {
2926ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2927ffd830a3SStefano Zampini   }
2928ffd830a3SStefano Zampini   if (n_vertices) {
2929ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2930ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2931ffd830a3SStefano Zampini   }
2932ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2933ffd830a3SStefano Zampini 
29345cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
29355cbda25cSStefano Zampini   dummy_vec = NULL;
29365cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
29375cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
29385cbda25cSStefano Zampini   }
29395cbda25cSStefano Zampini 
294088ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
294188ebb749SStefano Zampini   if (n_constraints) {
294272b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
294306656605SStefano Zampini     IS          is_aux;
294480677318SStefano Zampini     PetscScalar *array,*array2;
294506656605SStefano Zampini 
2946f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
294780677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
294888ebb749SStefano Zampini 
294925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
295025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
29518ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
295272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
295388ebb749SStefano Zampini 
295480677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
295580677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2956ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
295788ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
295806656605SStefano Zampini       const PetscScalar *row_cmat_values;
295906656605SStefano Zampini       const PetscInt    *row_cmat_indices;
296006656605SStefano Zampini       PetscInt          size_of_constraint,j;
296188ebb749SStefano Zampini 
296206656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
296306656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
2964ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
296506656605SStefano Zampini       }
296606656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
296706656605SStefano Zampini     }
2968ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
296906656605SStefano Zampini     if (F) {
297006656605SStefano Zampini       Mat B;
297106656605SStefano Zampini 
2972ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
2973a3df083aSStefano Zampini       if (need_benign_correction) {
2974df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2975a3df083aSStefano Zampini 
297672b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
297772b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2978a3df083aSStefano Zampini       }
297980677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
2980a3df083aSStefano Zampini       if (need_benign_correction) {
2981a3df083aSStefano Zampini         PetscScalar        *marr;
2982df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2983a3df083aSStefano Zampini 
2984a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
29855cbda25cSStefano Zampini         if (lda_rhs != n_R) {
29865cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
29875cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
29885cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
29895cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
29905cbda25cSStefano Zampini           }
29915cbda25cSStefano Zampini         } else {
2992a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
2993a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
29945cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2995a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2996a3df083aSStefano Zampini           }
29975cbda25cSStefano Zampini         }
2998a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
2999a3df083aSStefano Zampini       }
300006656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
300106656605SStefano Zampini     } else {
300280677318SStefano Zampini       PetscScalar *marr;
300380677318SStefano Zampini 
300480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
300506656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
3006ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3007ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
300806656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
300906656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
301006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
301106656605SStefano Zampini       }
301280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
301306656605SStefano Zampini     }
301480677318SStefano Zampini     if (!pcbddc->switch_static) {
301580677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
301680677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
301780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
301880677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
3019ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
302080677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
302180677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
302280677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
302380677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
302480677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
302580677318SStefano Zampini       }
302680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
302780677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
302872b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
302980677318SStefano Zampini     } else {
3030ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3031ffd830a3SStefano Zampini         IS dummy;
3032ffd830a3SStefano Zampini 
3033ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
303472b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
3035ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
3036ffd830a3SStefano Zampini       } else {
303780677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
303880677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
3039ffd830a3SStefano Zampini       }
304025084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
304180677318SStefano Zampini     }
304280677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
304380677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
304480677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
304506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
304606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
304780677318SStefano Zampini     if (isCHOL) {
304880677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
304980677318SStefano Zampini     } else {
305025084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
305180677318SStefano Zampini     }
305280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
305306656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
305425084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
305525084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
305625084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
305780677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
305872b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
305972b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
306006656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
306106656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
3062f4ddd8eeSStefano Zampini   }
3063fc227af8SStefano Zampini 
3064fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
306588ebb749SStefano Zampini   if (n_vertices) {
306606656605SStefano Zampini     IS is_aux;
30673a50541eSStefano Zampini 
3068b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
30696816873aSStefano Zampini       IS tis;
30706816873aSStefano Zampini 
30716816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
30726816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
30736816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
30746816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
30756816873aSStefano Zampini     } else {
30763a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
30776816873aSStefano Zampini     }
30789577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
30799577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
308004708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
308125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
308288ebb749SStefano Zampini   }
308388ebb749SStefano Zampini 
308488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
3085f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
308606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
308706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
308806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
308906656605SStefano Zampini     }
3090f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
309106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
309206656605SStefano Zampini       PetscScalar *marray;
309306656605SStefano Zampini 
309406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
309506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
3096f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
3097f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
3098f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
3099f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
3100f4ddd8eeSStefano Zampini     }
3101f4ddd8eeSStefano Zampini   }
310206656605SStefano Zampini 
3103f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
310406656605SStefano Zampini     PetscScalar *marray;
310588ebb749SStefano Zampini 
310606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31078eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
310806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
310988ebb749SStefano Zampini     }
31103301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
311106656605SStefano Zampini       n *= 2;
311288ebb749SStefano Zampini     }
311306656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
311406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
311506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
31168eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
311706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
311806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
311988ebb749SStefano Zampini     }
31203301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
312106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
31228eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
312306656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
312406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
312588ebb749SStefano Zampini       }
312688ebb749SStefano Zampini     } else {
3127c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
3128c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
31291b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
3130c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
3131c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
3132c0553b1fSStefano Zampini       }
313388ebb749SStefano Zampini     }
313406656605SStefano Zampini   }
3135019a44ceSStefano Zampini 
313606656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
31374f1b2e48SStefano Zampini   p0_lidx_I = NULL;
31384f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
3139d12edf2fSStefano Zampini     const PetscInt *idxs;
3140d12edf2fSStefano Zampini 
3141d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
31424f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
31434f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
31444f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
31454f1b2e48SStefano Zampini     }
3146d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
3147d12edf2fSStefano Zampini   }
3148d16cbb6bSStefano Zampini 
314906656605SStefano Zampini   /* vertices */
315006656605SStefano Zampini   if (n_vertices) {
315116f15bc4SStefano Zampini 
3152af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
315304708bb6SStefano Zampini 
315416f15bc4SStefano Zampini     if (n_R) {
315514393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
315606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
315716f15bc4SStefano Zampini       PetscScalar  *x,*y;
315804708bb6SStefano Zampini       PetscBool    isseqaij;
315906656605SStefano Zampini 
316021eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
316114393ed6SStefano Zampini       if (need_benign_correction) {
316214393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
316314393ed6SStefano Zampini         IS                     is_p0;
316414393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
316514393ed6SStefano Zampini 
316614393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
316714393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
316814393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
3169af25d912SStefano 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);
317014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
317114393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
317214393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
317314393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
317414393ed6SStefano Zampini       }
317514393ed6SStefano Zampini 
3176ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3177af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3178ffd830a3SStefano Zampini       } else {
3179ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3180ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3181ca92afb2SStefano Zampini         PetscInt       n;
3182ca92afb2SStefano Zampini         PetscBool      flg_row;
3183ffd830a3SStefano Zampini 
3184ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3185ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
31869d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3187ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3188ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3189ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3190ca92afb2SStefano Zampini           PetscInt j;
3191ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3192ffd830a3SStefano Zampini         }
3193ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3194ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3195ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3196ffd830a3SStefano Zampini       }
3197ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3198a3df083aSStefano Zampini       if (need_benign_correction) {
3199df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3200a3df083aSStefano Zampini         PetscScalar        *marr;
3201a3df083aSStefano Zampini 
3202a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
320314393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
320414393ed6SStefano Zampini 
320514393ed6SStefano Zampini                | 0 0  0 | (V)
320614393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
320714393ed6SStefano Zampini                | 0 0 -1 | (p0)
320814393ed6SStefano Zampini 
320914393ed6SStefano Zampini         */
3210df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
321114393ed6SStefano Zampini           const PetscScalar *vals;
321214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
321314393ed6SStefano Zampini           PetscInt          n,j,nz;
321414393ed6SStefano Zampini 
3215df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3216df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
321714393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
321814393ed6SStefano Zampini           for (j=0;j<n;j++) {
321914393ed6SStefano Zampini             PetscScalar val = vals[j];
322014393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
322114393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
322214393ed6SStefano Zampini           }
322314393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3224df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
322514393ed6SStefano Zampini         }
322672b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
322772b8c272SStefano Zampini       }
322872b8c272SStefano Zampini       if (F) {
322914393ed6SStefano Zampini         /* need to correct the rhs */
323072b8c272SStefano Zampini         if (need_benign_correction) {
323172b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
323272b8c272SStefano Zampini           PetscScalar        *marr;
323372b8c272SStefano Zampini 
323472b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
32355cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32365cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32375cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32385cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
32395cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32405cbda25cSStefano Zampini             }
32415cbda25cSStefano Zampini           } else {
3242a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3243a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
32445cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3245a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3246a3df083aSStefano Zampini             }
32475cbda25cSStefano Zampini           }
3248a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3249a3df083aSStefano Zampini         }
325006656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
325114393ed6SStefano Zampini         /* need to correct the solution */
3252a3df083aSStefano Zampini         if (need_benign_correction) {
3253df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3254a3df083aSStefano Zampini           PetscScalar        *marr;
3255a3df083aSStefano Zampini 
3256a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
32575cbda25cSStefano Zampini           if (lda_rhs != n_R) {
32585cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
32595cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
32605cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
32615cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
32625cbda25cSStefano Zampini             }
32635cbda25cSStefano Zampini           } else {
3264a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3265a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
32665cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3267a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3268a3df083aSStefano Zampini             }
32695cbda25cSStefano Zampini           }
3270a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3271a3df083aSStefano Zampini         }
327206656605SStefano Zampini       } else {
327306656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
327406656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3275ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3276ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
327706656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
327806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
327906656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
328006656605SStefano Zampini         }
328106656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
328206656605SStefano Zampini       }
328380677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3284ffd830a3SStefano Zampini       /* S_VV and S_CV */
328506656605SStefano Zampini       if (n_constraints) {
328606656605SStefano Zampini         Mat B;
328780677318SStefano Zampini 
3288ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
328980677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3290ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3291ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
329280677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329380677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
329480677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
329580677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
329680677318SStefano Zampini         }
3297ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
329880677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
329980677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3300ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
330180677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
330206656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3303ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3304ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
330506656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
330606656605SStefano Zampini       }
330704708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
330804708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3309511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
331004708bb6SStefano Zampini       }
3311ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3312ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3313ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3314ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3315ffd830a3SStefano Zampini       }
331606656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
331714393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
331814393ed6SStefano Zampini       if (need_benign_correction) {
3319df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
332014393ed6SStefano Zampini         PetscScalar      *marr,*sums;
332114393ed6SStefano Zampini 
332214393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
332314393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3324df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
332514393ed6SStefano Zampini           const PetscScalar *vals;
332614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
332714393ed6SStefano Zampini           PetscInt          n,j,nz;
332814393ed6SStefano Zampini 
3329df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3330df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
333114393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
333214393ed6SStefano Zampini             PetscInt k;
333314393ed6SStefano Zampini             sums[j] = 0.;
333414393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
333514393ed6SStefano Zampini           }
333614393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
333714393ed6SStefano Zampini           for (j=0;j<n;j++) {
333814393ed6SStefano Zampini             PetscScalar val = vals[j];
333914393ed6SStefano Zampini             PetscInt k;
334014393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
334114393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
334214393ed6SStefano Zampini             }
334314393ed6SStefano Zampini           }
334414393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3345df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
334614393ed6SStefano Zampini         }
334714393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
334814393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
334914393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
335014393ed6SStefano Zampini       }
335180677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
335206656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
335306656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
335406656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
335506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
335606656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
335706656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
335806656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3359d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3360019a44ceSStefano Zampini     } else {
3361d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3362d16cbb6bSStefano Zampini     }
336321eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3364d16cbb6bSStefano Zampini 
336506656605SStefano Zampini     /* coarse basis functions */
336606656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
336716f15bc4SStefano Zampini       PetscScalar *y;
336816f15bc4SStefano Zampini 
3369ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
337006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
337106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
337206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
337306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
337406656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
337506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
337606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
337706656605SStefano Zampini 
337806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
33794f1b2e48SStefano Zampini         PetscInt j;
33804f1b2e48SStefano Zampini 
338106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
338206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
338306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
33864f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
338706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
338806656605SStefano Zampini       }
338906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
339006656605SStefano Zampini     }
339104708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
339204708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
339306656605SStefano Zampini   }
33945cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
339506656605SStefano Zampini 
339606656605SStefano Zampini   if (n_constraints) {
339706656605SStefano Zampini     Mat B;
339806656605SStefano Zampini 
3399ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
340006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
340180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
340206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
340306656605SStefano Zampini     if (n_vertices) {
340480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
340580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
340680677318SStefano Zampini       } else {
340780677318SStefano Zampini         Mat S_VCt;
340880677318SStefano Zampini 
3409ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3410ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
341172b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3412ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3413ffd830a3SStefano Zampini         }
341480677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
341580677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
341680677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
341780677318SStefano Zampini       }
341806656605SStefano Zampini     }
341906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
342006656605SStefano Zampini     /* coarse basis functions */
342106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
342206656605SStefano Zampini       PetscScalar *y;
342306656605SStefano Zampini 
3424ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
342506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
342606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
342706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
343006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
343106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
34324f1b2e48SStefano Zampini         PetscInt j;
34334f1b2e48SStefano Zampini 
343406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
343506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
343606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
343706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
343806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
34394f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
344006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
344106656605SStefano Zampini       }
344206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
344306656605SStefano Zampini     }
344406656605SStefano Zampini   }
344580677318SStefano Zampini   if (n_constraints) {
344680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
344780677318SStefano Zampini   }
34484f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
344972b8c272SStefano Zampini 
345072b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
345172b8c272SStefano Zampini   if (pcbddc->benign_n) {
345272b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
345372b8c272SStefano Zampini     IS          is_dummy;
345472b8c272SStefano Zampini     PetscScalar *data;
345572b8c272SStefano Zampini     PetscInt    j;
345672b8c272SStefano Zampini 
345772b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
345872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
345972b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
346072b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
346186c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
346272b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
346372b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
346472b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
346572b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
346672b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
346772b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
346872b8c272SStefano Zampini       }
346972b8c272SStefano Zampini     }
347072b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
347172b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
347272b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
347372b8c272SStefano Zampini   }
3474019a44ceSStefano Zampini 
347506656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
34763301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3477ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3478ffd830a3SStefano Zampini     PetscScalar *marray;
347906656605SStefano Zampini 
348006656605SStefano Zampini     if (n_constraints) {
3481ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
348206656605SStefano Zampini 
3483af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
348406656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3485ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
348616f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
348706656605SStefano Zampini       if (n_vertices) {
3488ffd830a3SStefano Zampini         Mat S_VCT;
348906656605SStefano Zampini 
349006656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3491ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
349216f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
349306656605SStefano Zampini       }
3494ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
34955b782168SStefano Zampini     } else {
34965b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
349706656605SStefano Zampini     }
349816f15bc4SStefano Zampini     if (n_vertices && n_R) {
3499ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3500ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3501ffd830a3SStefano Zampini       PetscInt       n;
3502ffd830a3SStefano Zampini       PetscBool      flg_row;
350306656605SStefano Zampini 
3504ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3505af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3506ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3507ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3508ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3509ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3510ffd830a3SStefano Zampini         PetscInt j;
3511ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3512ffd830a3SStefano Zampini       }
3513ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3514ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3515ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
351606656605SStefano Zampini     }
351706656605SStefano Zampini 
3518ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3519ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3520ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3521ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3522ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
352306656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
352406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
352506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
352606656605SStefano Zampini     }
3527ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
35285b782168SStefano Zampini     if (B_C) {
3529ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3530ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3531ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3532ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3533ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3534ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3535ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
353606656605SStefano Zampini       }
3537ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
35385b782168SStefano Zampini     }
353906656605SStefano Zampini     /* coarse basis functions */
354006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
354106656605SStefano Zampini       PetscScalar *y;
354206656605SStefano Zampini 
3543ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
354406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
354506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
354606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
354706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
354806656605SStefano Zampini       if (i<n_vertices) {
354906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
355006656605SStefano Zampini       }
355106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
355206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
355306656605SStefano Zampini 
355406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
355506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
355606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
355706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
355806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
355906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
356006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
356106656605SStefano Zampini       }
356206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
356306656605SStefano Zampini     }
3564ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3565ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
356606656605SStefano Zampini   }
3567d62866d3SStefano Zampini   /* free memory */
356888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
356906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
357006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
357106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
357206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3573d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3574d62866d3SStefano Zampini   if (n_vertices) {
3575d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3576d62866d3SStefano Zampini   }
3577d62866d3SStefano Zampini   if (n_constraints) {
3578d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3579d62866d3SStefano Zampini   }
358088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
358188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
358288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3583d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
358488ebb749SStefano Zampini     Mat         coarse_sub_mat;
358525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
358688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
358788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
358888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
35898bec7fa6SStefano Zampini     Mat         C_B,CPHI;
35908bec7fa6SStefano Zampini     IS          is_dummy;
35918bec7fa6SStefano Zampini     Vec         mones;
359288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
359388ebb749SStefano Zampini     PetscReal   real_value;
359488ebb749SStefano Zampini 
3595a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3596a3df083aSStefano Zampini       Mat A;
3597a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3598a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3599a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3600a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3601a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3602a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3603a3df083aSStefano Zampini     } else {
360488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
360588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
360688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
360788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3608a3df083aSStefano Zampini     }
360988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
361088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3611ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
361288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
361388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
361488ebb749SStefano Zampini     }
361588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
361688ebb749SStefano Zampini 
361725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36183301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
361925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3620ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
362188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
362288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
362388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
362488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
362588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
362688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
362788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
362888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
362988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
363088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
363188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
363288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
363388ebb749SStefano Zampini     } else {
363488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
363588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
363688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
363788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
363888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
363988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
364088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
364188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
364288ebb749SStefano Zampini     }
364388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
364488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
364588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3646511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
36474f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3648fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3649d12edf2fSStefano Zampini       PetscScalar *data,*data2;
36504f1b2e48SStefano Zampini       PetscInt    j;
3651d12edf2fSStefano Zampini 
36524f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3653fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3654d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
365586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3656d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3657d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
36584f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
36594f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3660d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
36614f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
36624f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
36634f1b2e48SStefano Zampini         }
3664d12edf2fSStefano Zampini       }
3665d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3666d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3667d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3668d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3669d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3670d12edf2fSStefano Zampini     }
3671d12edf2fSStefano Zampini #if 0
3672d12edf2fSStefano Zampini   {
3673d12edf2fSStefano Zampini     PetscViewer viewer;
3674d12edf2fSStefano Zampini     char filename[256];
3675ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3676d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3677d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3678ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3679ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3680ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3681d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
368272b8c272SStefano Zampini     if (save_change) {
368372b8c272SStefano Zampini       Mat phi_B;
368472b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
368572b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
368672b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
368772b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
368872b8c272SStefano Zampini     } else {
3689ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3690ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
369172b8c272SStefano Zampini     }
3692ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3693ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3694ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3695ffd830a3SStefano Zampini     }
3696ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3697ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3698ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3699ffd830a3SStefano Zampini     }
370072b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3701ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3702ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3703ffd830a3SStefano Zampini     }
3704d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3705d12edf2fSStefano Zampini   }
3706d12edf2fSStefano Zampini #endif
370781d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
37088bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
37091575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
371006656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
37118bec7fa6SStefano Zampini 
37128bec7fa6SStefano Zampini     /* check constraints */
3713a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3714a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
37154f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
37168bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3717a00504b5SStefano Zampini     } else {
3718a00504b5SStefano Zampini       PetscScalar *data;
3719a00504b5SStefano Zampini       Mat         tmat;
3720a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3721a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3722a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3723a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3724a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3725a00504b5SStefano Zampini     }
37268bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
37278bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
37288bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
37298bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3730bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3731ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3732bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3733bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3734bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3735bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3736bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
373788ebb749SStefano Zampini     }
37388bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
37398bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
37408bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37418bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
374225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
374388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
374488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
374588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
374688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
374788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
374888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
374988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
375088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
375188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
375288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3753ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
375488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
375588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
375688ebb749SStefano Zampini     }
375788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
375888ebb749SStefano Zampini   }
37598629588bSStefano Zampini   /* get back data */
37608629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
376188ebb749SStefano Zampini   PetscFunctionReturn(0);
376288ebb749SStefano Zampini }
376388ebb749SStefano Zampini 
376488ebb749SStefano Zampini #undef __FUNCT__
3765d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3766d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3767aa0d41d4SStefano Zampini {
3768d65f70fdSStefano Zampini   Mat            *work_mat;
3769d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3770d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3771c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3772aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3773aa0d41d4SStefano Zampini 
3774aa0d41d4SStefano Zampini   PetscFunctionBegin;
3775d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3776d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3777d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3778d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3779aa0d41d4SStefano Zampini 
3780d65f70fdSStefano Zampini   if (!rsorted) {
3781906d46d4SStefano Zampini     const PetscInt *idxs;
3782906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3783aa0d41d4SStefano Zampini 
3784d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3785d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3786d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3787d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3788aa0d41d4SStefano Zampini     }
3789d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3790d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3791d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3792d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3793aa0d41d4SStefano Zampini     }
3794d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3795d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3796d65f70fdSStefano Zampini   } else {
3797d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3798d65f70fdSStefano Zampini     isrow_s = isrow;
3799aa0d41d4SStefano Zampini   }
3800906d46d4SStefano Zampini 
3801d65f70fdSStefano Zampini   if (!csorted) {
3802d65f70fdSStefano Zampini     if (isrow == iscol) {
3803d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3804d65f70fdSStefano Zampini       iscol_s = isrow_s;
3805d65f70fdSStefano Zampini     } else {
3806d65f70fdSStefano Zampini       const PetscInt *idxs;
3807d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3808906d46d4SStefano Zampini 
3809d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3810d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3811d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3812d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3813d65f70fdSStefano Zampini       }
3814d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3815d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3816d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3817d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3818d65f70fdSStefano Zampini       }
3819d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3820d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3821d65f70fdSStefano Zampini     }
3822d65f70fdSStefano Zampini   } else {
3823d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3824d65f70fdSStefano Zampini     iscol_s = iscol;
3825d65f70fdSStefano Zampini   }
3826d65f70fdSStefano Zampini 
3827d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3828d65f70fdSStefano Zampini 
3829d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3830906d46d4SStefano Zampini     Mat      new_mat;
3831d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3832906d46d4SStefano Zampini 
3833d65f70fdSStefano Zampini     if (!rsorted) {
3834d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3835d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3836d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3837d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3838906d46d4SStefano Zampini       }
3839d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3840d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3841d65f70fdSStefano Zampini     } else {
3842d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3843906d46d4SStefano Zampini     }
3844d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3845d65f70fdSStefano Zampini 
3846d65f70fdSStefano Zampini     if (!csorted) {
3847d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3848d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3849d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3850d65f70fdSStefano Zampini       } else {
3851d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3852d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3853d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3854d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3855d65f70fdSStefano Zampini         }
3856d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3857d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3858d65f70fdSStefano Zampini       }
3859d65f70fdSStefano Zampini     } else {
3860d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3861d65f70fdSStefano Zampini     }
3862d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3863d65f70fdSStefano Zampini 
3864d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3865d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3866d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3867d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3868d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3869d65f70fdSStefano Zampini   }
3870d65f70fdSStefano Zampini 
3871d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3872d65f70fdSStefano Zampini   *B = work_mat[0];
3873d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3874d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3875d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3876d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3877d65f70fdSStefano Zampini }
3878d65f70fdSStefano Zampini 
3879d65f70fdSStefano Zampini #undef __FUNCT__
38805e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
38815e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3882aa0d41d4SStefano Zampini {
3883aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
38845e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3885d65f70fdSStefano Zampini   Mat            new_mat;
38865e8657edSStefano Zampini   IS             is_local,is_global;
3887d65f70fdSStefano Zampini   PetscInt       local_size;
3888d65f70fdSStefano Zampini   PetscBool      isseqaij;
3889aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3890aa0d41d4SStefano Zampini 
3891aa0d41d4SStefano Zampini   PetscFunctionBegin;
3892aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
38935e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
38945e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3895b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3896aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3897d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3898aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3899906d46d4SStefano Zampini 
3900906d46d4SStefano Zampini   /* check */
3901906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3902906d46d4SStefano Zampini     Vec       x,x_change;
3903906d46d4SStefano Zampini     PetscReal error;
3904906d46d4SStefano Zampini 
39055e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3906906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
39075e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3908e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3909e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3910d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3911e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3912e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3913906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3914906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3915906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3916906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3917906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3918906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3919906d46d4SStefano Zampini   }
3920906d46d4SStefano Zampini 
392122d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
39229b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
392322d5777bSStefano Zampini   if (isseqaij) {
3924a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3925a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3926aa0d41d4SStefano Zampini   } else {
3927a00504b5SStefano Zampini     Mat work_mat;
39281cf9b237SStefano Zampini 
3929a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3930aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3931a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
39321d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3933aa0d41d4SStefano Zampini   }
39343301b35fSStefano Zampini   if (matis->A->symmetric_set) {
39353301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3936e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39373301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3938e496cd5dSStefano Zampini #endif
39393301b35fSStefano Zampini   }
3940d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3941aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3942aa0d41d4SStefano Zampini }
3943aa0d41d4SStefano Zampini 
3944aa0d41d4SStefano Zampini #undef __FUNCT__
3945a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
39468ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3947a64d13efSStefano Zampini {
3948a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3949a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3950d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
395153892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
39523a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
39533a50541eSStefano Zampini   PetscInt        vbs,bs;
39546816873aSStefano Zampini   PetscBT         bitmask=NULL;
3955a64d13efSStefano Zampini   PetscErrorCode  ierr;
3956a64d13efSStefano Zampini 
3957a64d13efSStefano Zampini   PetscFunctionBegin;
3958b23d619eSStefano Zampini   /*
3959b23d619eSStefano Zampini     No need to setup local scatters if
3960b23d619eSStefano Zampini       - primal space is unchanged
3961b23d619eSStefano Zampini         AND
3962b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
3963b23d619eSStefano Zampini         AND
3964b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
3965b23d619eSStefano Zampini   */
3966b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
3967f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
3968f4ddd8eeSStefano Zampini   }
3969f4ddd8eeSStefano Zampini   /* destroy old objects */
3970f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3971f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3972f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3973a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
3974b371cd4fSStefano Zampini   n_B = pcis->n_B;
3975b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
3976b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
39773a50541eSStefano Zampini 
3978a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
39796816873aSStefano Zampini 
398053892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
3981b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
3982854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
3983a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
3984a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
39850e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
3986a64d13efSStefano Zampini     }
3987a64d13efSStefano Zampini 
3988a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
39894641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
39906816873aSStefano Zampini         idx_R_local[n_R++] = i;
3991a64d13efSStefano Zampini       }
3992a64d13efSStefano Zampini     }
3993df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
3994df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
39956816873aSStefano Zampini 
3996df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3997df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
39986816873aSStefano Zampini   }
39993a50541eSStefano Zampini 
40003a50541eSStefano Zampini   /* Block code */
40013a50541eSStefano Zampini   vbs = 1;
40023a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
40033a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
40043a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
40053a50541eSStefano Zampini     PetscInt  *vary;
4006b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
4007785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
40083a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
4009d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
4010d3df7717SStefano 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 */
40110e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
4012d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
40133a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
40143a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
40153a50541eSStefano Zampini           break;
40163a50541eSStefano Zampini         }
40173a50541eSStefano Zampini       }
4018d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
4019d3df7717SStefano Zampini     } else {
4020d3df7717SStefano Zampini       /* Verify directly the R set */
4021d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
4022d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
4023d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
4024d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
4025d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
4026d3df7717SStefano Zampini             break;
4027d3df7717SStefano Zampini           }
4028d3df7717SStefano Zampini         }
4029d3df7717SStefano Zampini       }
4030d3df7717SStefano Zampini     }
40313a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
40323a50541eSStefano Zampini       vbs = bs;
40333a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
40343a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
40353a50541eSStefano Zampini       }
40363a50541eSStefano Zampini     }
40373a50541eSStefano Zampini   }
40383a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
4039b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
4040df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
404153892102SStefano Zampini 
4042df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4043df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
404453892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
4045df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
404653892102SStefano Zampini   } else {
40473a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
404853892102SStefano Zampini   }
4049a64d13efSStefano Zampini 
4050a64d13efSStefano Zampini   /* print some info if requested */
4051a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
4052a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4053a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
40541575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4055a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
4056a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
40574f1b2e48SStefano 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);
4058a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4059a64d13efSStefano Zampini   }
4060a64d13efSStefano Zampini 
4061a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
4062b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
40636816873aSStefano Zampini     IS       is_aux1,is_aux2;
40646816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
40656816873aSStefano Zampini 
40663a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4067854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
4068854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
4069a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
40704641a718SStefano Zampini     for (i=0; i<n_D; i++) {
40714641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
40724641a718SStefano Zampini     }
4073a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4074a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
40754641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
40764641a718SStefano Zampini         aux_array1[j++] = i;
4077a64d13efSStefano Zampini       }
4078a64d13efSStefano Zampini     }
4079a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4080a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4081a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
40824641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
40834641a718SStefano Zampini         aux_array2[j++] = i;
4084a64d13efSStefano Zampini       }
4085a64d13efSStefano Zampini     }
4086a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4087a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
4088a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
4089a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4090a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
4091a64d13efSStefano Zampini 
40928eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
4093785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
4094a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
40954641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
40964641a718SStefano Zampini           aux_array1[j++] = i;
4097a64d13efSStefano Zampini         }
4098a64d13efSStefano Zampini       }
4099a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
4100a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
4101a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
4102a64d13efSStefano Zampini     }
41034641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
41043a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
4105d62866d3SStefano Zampini   } else {
4106df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
41076816873aSStefano Zampini     IS                 tis;
41086816873aSStefano Zampini     PetscInt           schur_size;
41096816873aSStefano Zampini 
4110df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
41116816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
4112df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
41136816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
41146816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41156816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
41166816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
41176816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
4118d62866d3SStefano Zampini     }
4119d62866d3SStefano Zampini   }
4120a64d13efSStefano Zampini   PetscFunctionReturn(0);
4121a64d13efSStefano Zampini }
4122a64d13efSStefano Zampini 
4123304d26faSStefano Zampini 
4124304d26faSStefano Zampini #undef __FUNCT__
4125304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
4126684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
4127304d26faSStefano Zampini {
4128304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4129304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
4130304d26faSStefano Zampini   PC             pc_temp;
4131304d26faSStefano Zampini   Mat            A_RR;
4132f4ddd8eeSStefano Zampini   MatReuse       reuse;
4133304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
4134304d26faSStefano Zampini   PetscReal      value;
413504708bb6SStefano Zampini   PetscInt       n_D,n_R;
4136c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
4137304d26faSStefano Zampini   PetscErrorCode ierr;
4138e604994aSStefano Zampini   /* prefixes stuff */
4139312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
4140e604994aSStefano Zampini   size_t         len;
4141304d26faSStefano Zampini 
4142304d26faSStefano Zampini   PetscFunctionBegin;
4143304d26faSStefano Zampini 
4144e604994aSStefano Zampini   /* compute prefixes */
4145e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
4146e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
4147e604994aSStefano Zampini   if (!pcbddc->current_level) {
4148e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4149e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
4150e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4151e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4152e604994aSStefano Zampini   } else {
4153e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
4154312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
4155e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
4156e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
4157312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
4158312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
415934d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
416034d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
4161e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
4162e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
4163e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
4164e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
4165e604994aSStefano Zampini   }
4166e604994aSStefano Zampini 
4167304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
4168684f6988SStefano Zampini   if (dirichlet) {
4169d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4170450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
41719a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
4172450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
4173a3df083aSStefano Zampini         Mat    A_IIn;
4174a3df083aSStefano Zampini 
4175a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
4176a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4177a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4178a3df083aSStefano Zampini       }
4179450f8f5eSStefano Zampini     }
41803301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
41813301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4182964fefecSStefano Zampini     }
4183ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4184964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4185304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4186304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4187304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4188304d26faSStefano Zampini       /* default */
4189304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4190e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
41919577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4192304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
41939577ea80SStefano Zampini       if (issbaij) {
41949577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
41959577ea80SStefano Zampini       } else {
4196304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
41979577ea80SStefano Zampini       }
4198304d26faSStefano Zampini       /* Allow user's customization */
4199304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4200304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4201304d26faSStefano Zampini     }
4202d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4203b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4204df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4205d62866d3SStefano Zampini 
4206df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4207d5574798SStefano Zampini     }
4208304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4209304d26faSStefano Zampini     if (!n_D) {
4210304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4211304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4212304d26faSStefano Zampini     }
4213304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4214304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4215304d26faSStefano Zampini     /* set ksp_D into pcis data */
4216304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4217304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4218304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4219684f6988SStefano Zampini   }
4220304d26faSStefano Zampini 
4221304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4222684f6988SStefano Zampini   A_RR = 0;
4223684f6988SStefano Zampini   if (neumann) {
4224d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
422504708bb6SStefano Zampini     PetscInt        ibs,mbs;
422604708bb6SStefano Zampini     PetscBool       issbaij;
422704708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4228f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
42298ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4230f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4231f4ddd8eeSStefano Zampini       PetscInt nn_R;
423281d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4233f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4234f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4235f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4236f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4237f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4238f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4239f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4240727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4241f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4242f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4243f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4244f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4245f4ddd8eeSStefano Zampini         }
4246f4ddd8eeSStefano Zampini       }
4247f4ddd8eeSStefano Zampini       /* last check */
4248d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4249f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4250f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4251f4ddd8eeSStefano Zampini       }
4252f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4253f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4254f4ddd8eeSStefano Zampini     }
4255a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4256af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4257af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
425804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
425904708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
426004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
426104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
426204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4263af732b37SStefano Zampini       } else {
4264511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
42656816873aSStefano Zampini       }
426604708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
426704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
426804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
426904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
427004708bb6SStefano Zampini       } else {
4271511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
427204708bb6SStefano Zampini       }
427304708bb6SStefano Zampini     }
4274a00504b5SStefano Zampini     /* extract A_RR */
4275b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4276a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4277a00504b5SStefano Zampini 
4278a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
427916e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4280a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
428116e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
428216e386b8SStefano Zampini         } else {
4283a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4284a00504b5SStefano Zampini         }
4285a00504b5SStefano Zampini       } else {
4286a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4287a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4288a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4289a00504b5SStefano Zampini       }
4290a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4291f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
429216e386b8SStefano Zampini     }
42933301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
42943301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
42956816873aSStefano Zampini     }
4296f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4297304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4298304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4299304d26faSStefano Zampini       /* default */
4300304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4301e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4302304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
43039577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
43049577ea80SStefano Zampini       if (issbaij) {
43059577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
43069577ea80SStefano Zampini       } else {
4307304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
43089577ea80SStefano Zampini       }
4309304d26faSStefano Zampini       /* Allow user's customization */
4310304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4311304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4312304d26faSStefano Zampini     }
4313304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4314304d26faSStefano Zampini     if (!n_R) {
4315304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4316304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4317304d26faSStefano Zampini     }
43185cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4319df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4320b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4321df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4322d62866d3SStefano Zampini 
4323df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4324d62866d3SStefano Zampini     }
4325304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4326304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4327684f6988SStefano Zampini   }
4328304d26faSStefano Zampini 
4329684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4330684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
43311575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4332684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4333684f6988SStefano Zampini   }
4334c7017625SStefano Zampini 
4335c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4336c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4337c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4338c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4339c7017625SStefano Zampini   }
4340c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4341c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4342c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4343c7017625SStefano Zampini   }
4344c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4345c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4346c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4347c7017625SStefano Zampini   }
4348c7017625SStefano Zampini 
4349c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4350c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4351684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
43520fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
43530fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
43540fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
43550fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
43560fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4357e604994aSStefano 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);
4358c7017625SStefano Zampini       if (check_corr[0]) {
4359c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4360c7017625SStefano Zampini       }
4361304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4362304d26faSStefano Zampini     }
4363684f6988SStefano Zampini     if (neumann) { /* Neumann */
43640fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
43650fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
43660fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
43670fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
43680fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4369e604994aSStefano 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);
4370c7017625SStefano Zampini       if (check_corr[1]) {
4371c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4372c7017625SStefano Zampini       }
4373304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4374304d26faSStefano Zampini     }
4375684f6988SStefano Zampini   }
43765cbda25cSStefano Zampini   /* free Neumann problem's matrix */
43775cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4378304d26faSStefano Zampini   PetscFunctionReturn(0);
4379304d26faSStefano Zampini }
4380304d26faSStefano Zampini 
4381304d26faSStefano Zampini #undef __FUNCT__
4382ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
438380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4384674ae819SStefano Zampini {
4385674ae819SStefano Zampini   PetscErrorCode  ierr;
4386674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4387be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4388b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4389674ae819SStefano Zampini 
4390674ae819SStefano Zampini   PetscFunctionBegin;
4391b334f244SStefano Zampini   if (!reuse_solver) {
439280677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
439320c7b377SStefano Zampini   }
439480677318SStefano Zampini   if (!pcbddc->switch_static) {
439580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
439680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
439780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
439820c7b377SStefano Zampini     }
4399b334f244SStefano Zampini     if (!reuse_solver) {
440080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
440180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
440220c7b377SStefano Zampini     } else {
4403df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4404be83ff47SStefano Zampini 
4405df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4406df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
440720c7b377SStefano Zampini     }
4408be83ff47SStefano Zampini   } else {
440980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
441080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
441180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
441280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
441380677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
441480677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
441580677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
441680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
441780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4418674ae819SStefano Zampini     }
4419674ae819SStefano Zampini   }
4420b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
442180677318SStefano Zampini     if (applytranspose) {
442280677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
442380677318SStefano Zampini     } else {
442480677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
442580677318SStefano Zampini     }
4426be83ff47SStefano Zampini   } else {
4427df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4428be83ff47SStefano Zampini 
4429be83ff47SStefano Zampini     if (applytranspose) {
4430df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4431be83ff47SStefano Zampini     } else {
4432df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4433be83ff47SStefano Zampini     }
4434be83ff47SStefano Zampini   }
443580677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
443680677318SStefano Zampini   if (!pcbddc->switch_static) {
4437b334f244SStefano Zampini     if (!reuse_solver) {
443880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
443980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4440be83ff47SStefano Zampini     } else {
4441df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4442be83ff47SStefano Zampini 
4443df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4444df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4445be83ff47SStefano Zampini     }
444680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
444780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
444880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
444980677318SStefano Zampini     }
445080677318SStefano Zampini   } else {
445180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
445280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
445380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
445480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
445580677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
445680677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
445780677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
445880677318SStefano Zampini     }
445980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
446080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
446180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
446280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4463674ae819SStefano Zampini   }
4464674ae819SStefano Zampini   PetscFunctionReturn(0);
4465674ae819SStefano Zampini }
4466674ae819SStefano Zampini 
4467dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4468674ae819SStefano Zampini #undef __FUNCT__
4469674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4470dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4471674ae819SStefano Zampini {
4472674ae819SStefano Zampini   PetscErrorCode ierr;
4473674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4474674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4475674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4476674ae819SStefano Zampini 
4477674ae819SStefano Zampini   PetscFunctionBegin;
4478dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
44794fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4480dc359a40SStefano Zampini     if (applytranspose) {
4481674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
44828eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4483dc359a40SStefano Zampini     } else {
4484674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4485674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
448615aaf578SStefano Zampini     }
44874fee134fSStefano Zampini   } else {
44884fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
44894fee134fSStefano Zampini   }
4490efc2fbd9SStefano Zampini 
4491efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
44924f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4493efc2fbd9SStefano Zampini     PetscScalar *array;
44944f1b2e48SStefano Zampini     PetscInt    j;
4495efc2fbd9SStefano Zampini 
4496efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
44974f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4498efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4499efc2fbd9SStefano Zampini   }
4500efc2fbd9SStefano Zampini 
450112edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
450212edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
450312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
450512edc857SStefano Zampini 
45069f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
450712edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
450851694757SStefano Zampini     Mat          coarse_mat;
4509964fefecSStefano Zampini     Vec          rhs,sol;
451051694757SStefano Zampini     MatNullSpace nullsp;
451127b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4512964fefecSStefano Zampini 
451327b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
451427b6a85dSStefano Zampini       PC        coarse_pc;
451527b6a85dSStefano Zampini 
451627b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
451727b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
451827b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
451927b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
452027b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
452127b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
45223bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
452327b6a85dSStefano Zampini       }
452427b6a85dSStefano Zampini     }
4525964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4526964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
452751694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
452851694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
452951694757SStefano Zampini     if (nullsp) {
453051694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
453151694757SStefano Zampini     }
453212edc857SStefano Zampini     if (applytranspose) {
45339a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4534964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
45352701bc32SStefano Zampini     } else {
45361f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
45372701bc32SStefano Zampini         PC        coarse_pc;
45382701bc32SStefano Zampini 
45392701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
45402701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
45413e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
45422701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
454312edc857SStefano Zampini       } else {
4544964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
454512edc857SStefano Zampini       }
45462701bc32SStefano Zampini     }
45471d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
454827b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
454927b6a85dSStefano Zampini       PC        coarse_pc;
455027b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
455127b6a85dSStefano Zampini 
455227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
455327b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
455427b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
45553bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
455627b6a85dSStefano Zampini     }
455751694757SStefano Zampini     if (nullsp) {
455851694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
455951694757SStefano Zampini     }
456012edc857SStefano Zampini   }
4561674ae819SStefano Zampini 
4562674ae819SStefano Zampini   /* Local solution on R nodes */
45634fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
456480677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
45659f00e9b4SStefano Zampini   }
45669f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
45679f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
456812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4569674ae819SStefano Zampini 
45704fee134fSStefano Zampini   /* Sum contributions from the two levels */
45714fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4572dc359a40SStefano Zampini     if (applytranspose) {
4573dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4574dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4575dc359a40SStefano Zampini     } else {
4576674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
45778eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4578dc359a40SStefano Zampini     }
4579efc2fbd9SStefano Zampini     /* store p0 */
45804f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4581efc2fbd9SStefano Zampini       PetscScalar *array;
45824f1b2e48SStefano Zampini       PetscInt    j;
4583efc2fbd9SStefano Zampini 
4584efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
45854f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4586efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4587efc2fbd9SStefano Zampini     }
45884fee134fSStefano Zampini   } else { /* expand the coarse solution */
45894fee134fSStefano Zampini     if (applytranspose) {
45904fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
45914fee134fSStefano Zampini     } else {
45924fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
45934fee134fSStefano Zampini     }
45944fee134fSStefano Zampini   }
4595674ae819SStefano Zampini   PetscFunctionReturn(0);
4596674ae819SStefano Zampini }
4597674ae819SStefano Zampini 
4598674ae819SStefano Zampini #undef __FUNCT__
4599674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
460012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4601674ae819SStefano Zampini {
4602674ae819SStefano Zampini   PetscErrorCode ierr;
4603674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
460458da7f69SStefano Zampini   PetscScalar    *array;
460512edc857SStefano Zampini   Vec            from,to;
4606674ae819SStefano Zampini 
4607674ae819SStefano Zampini   PetscFunctionBegin;
460812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
460912edc857SStefano Zampini     from = pcbddc->coarse_vec;
461012edc857SStefano Zampini     to = pcbddc->vec1_P;
461112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
461212edc857SStefano Zampini       Vec tvec;
461358da7f69SStefano Zampini 
461458da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
461558da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
461612edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
461758da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
461858da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
461958da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
462012edc857SStefano Zampini     }
462112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
462212edc857SStefano Zampini     from = pcbddc->vec1_P;
462312edc857SStefano Zampini     to = pcbddc->coarse_vec;
462412edc857SStefano Zampini   }
462512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4626674ae819SStefano Zampini   PetscFunctionReturn(0);
4627674ae819SStefano Zampini }
4628674ae819SStefano Zampini 
4629674ae819SStefano Zampini #undef __FUNCT__
4630674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
463112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4632674ae819SStefano Zampini {
4633674ae819SStefano Zampini   PetscErrorCode ierr;
4634674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
463558da7f69SStefano Zampini   PetscScalar    *array;
463612edc857SStefano Zampini   Vec            from,to;
4637674ae819SStefano Zampini 
4638674ae819SStefano Zampini   PetscFunctionBegin;
463912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
464012edc857SStefano Zampini     from = pcbddc->coarse_vec;
464112edc857SStefano Zampini     to = pcbddc->vec1_P;
464212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
464312edc857SStefano Zampini     from = pcbddc->vec1_P;
464412edc857SStefano Zampini     to = pcbddc->coarse_vec;
464512edc857SStefano Zampini   }
464612edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
464712edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
464812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
464912edc857SStefano Zampini       Vec tvec;
465058da7f69SStefano Zampini 
465112edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
465258da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
465358da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
465458da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
465558da7f69SStefano Zampini     }
465658da7f69SStefano Zampini   } else {
465758da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
465858da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
465912edc857SStefano Zampini     }
466012edc857SStefano Zampini   }
4661674ae819SStefano Zampini   PetscFunctionReturn(0);
4662674ae819SStefano Zampini }
4663674ae819SStefano Zampini 
4664984c4197SStefano Zampini /* uncomment for testing purposes */
4665984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4666674ae819SStefano Zampini #undef __FUNCT__
4667674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4668674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4669674ae819SStefano Zampini {
4670674ae819SStefano Zampini   PetscErrorCode    ierr;
4671674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4672674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4673674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4674984c4197SStefano Zampini   /* one and zero */
4675984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4676984c4197SStefano Zampini   /* space to store constraints and their local indices */
46779162d606SStefano Zampini   PetscScalar       *constraints_data;
46789162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
46799162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
46809162d606SStefano Zampini   PetscInt          *constraints_n;
4681984c4197SStefano Zampini   /* iterators */
4682b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4683984c4197SStefano Zampini   /* BLAS integers */
4684e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4685e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4686c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4687727cdba6SStefano Zampini   /* reuse */
46880e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
46890e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4690984c4197SStefano Zampini   /* change of basis */
4691b3d85658SStefano Zampini   PetscBool         qr_needed;
46929162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4693984c4197SStefano Zampini   /* auxiliary stuff */
469464efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
46958a0068c3SStefano Zampini   PetscInt          ncc;
4696984c4197SStefano Zampini   /* some quantities */
469745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4698a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4699984c4197SStefano Zampini 
4700674ae819SStefano Zampini   PetscFunctionBegin;
47018e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
47028e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47038e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
470416909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4705088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4706088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
47070e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
47080e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
47090e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47100e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
47110e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4712088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4713cf5a6209SStefano Zampini 
4714cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
47159162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4716cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4717cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4718cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4719cf5a6209SStefano Zampini     PetscScalar  *array;
4720cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4721cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4722674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4723b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4724674ae819SStefano Zampini     PetscScalar  *work;
4725674ae819SStefano Zampini     PetscReal    *singular_vals;
4726674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4727674ae819SStefano Zampini     PetscReal    *rwork;
4728674ae819SStefano Zampini #endif
4729674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4730674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4731674ae819SStefano Zampini #else
4732964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4733964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4734674ae819SStefano Zampini #endif
4735674ae819SStefano Zampini 
4736674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4737d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4738e4d548c7SStefano Zampini     /* print some info */
47391f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4740e4d548c7SStefano Zampini       PetscInt nv;
4741e4d548c7SStefano Zampini 
4742c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4743e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4744e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4745e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4746e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4747e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4748e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4749e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4750e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4751e4d548c7SStefano Zampini     }
4752e4d548c7SStefano Zampini 
4753d06fc5fdSStefano Zampini     /* free unneeded index sets */
4754d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4755d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4756674ae819SStefano Zampini     }
4757d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4758d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4759d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4760d06fc5fdSStefano Zampini       }
4761d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4762d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4763d06fc5fdSStefano Zampini     }
4764d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4765d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4766d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4767d06fc5fdSStefano Zampini       }
4768d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4769d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4770d06fc5fdSStefano Zampini     }
477170022509SStefano Zampini 
4772674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4773674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4774674ae819SStefano Zampini     if (nearnullsp) {
4775674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4776f4ddd8eeSStefano Zampini       /* remove any stored info */
4777f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4778f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4779f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4780f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4781f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4782473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4783f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4784f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4785f4ddd8eeSStefano Zampini       }
4786984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4787984c4197SStefano Zampini       nnsp_size = 0;
4788674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4789674ae819SStefano Zampini     }
4790984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4791984c4197SStefano Zampini     max_constraints = nnsp_size;
4792984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4793984c4197SStefano Zampini 
4794674ae819SStefano Zampini     /*
4795674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
47969162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
47979162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
47989162d606SStefano Zampini          There can be multiple constraints per connected component
4799674ae819SStefano Zampini                                                                                                                                                            */
4800674ae819SStefano Zampini     n_vertices = 0;
4801674ae819SStefano Zampini     if (ISForVertices) {
4802674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4803674ae819SStefano Zampini     }
48049162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
48059162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
48069162d606SStefano Zampini 
48079162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
48089162d606SStefano Zampini     total_counts *= max_constraints;
4809674ae819SStefano Zampini     total_counts += n_vertices;
48104641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
48119162d606SStefano Zampini 
4812674ae819SStefano Zampini     total_counts = 0;
4813674ae819SStefano Zampini     max_size_of_constraint = 0;
4814674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
48159162d606SStefano Zampini       IS used_is;
4816674ae819SStefano Zampini       if (i<n_ISForEdges) {
48179162d606SStefano Zampini         used_is = ISForEdges[i];
4818674ae819SStefano Zampini       } else {
48199162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4820674ae819SStefano Zampini       }
48219162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4822674ae819SStefano Zampini       total_counts += j;
4823674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4824674ae819SStefano Zampini     }
48259162d606SStefano 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);
48269162d606SStefano Zampini 
4827984c4197SStefano Zampini     /* get local part of global near null space vectors */
4828785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4829984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4830984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4831e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4832e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4833984c4197SStefano Zampini     }
4834674ae819SStefano Zampini 
4835242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4836242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4837a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4838242a89d7SStefano Zampini 
4839984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4840a773dcb8SStefano Zampini     if (!skip_lapack) {
4841674ae819SStefano Zampini       PetscScalar temp_work;
4842911cabfeSStefano Zampini 
4843674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4844984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4845785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4846785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4847785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4848674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4849785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4850674ae819SStefano Zampini #endif
4851674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4852c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4853c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4854674ae819SStefano Zampini       lwork = -1;
4855674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4856674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4857c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4858674ae819SStefano Zampini #else
4859c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4860674ae819SStefano Zampini #endif
4861674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4862984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4863674ae819SStefano Zampini #else /* on missing GESVD */
4864674ae819SStefano Zampini       /* SVD */
4865674ae819SStefano Zampini       PetscInt max_n,min_n;
4866674ae819SStefano Zampini       max_n = max_size_of_constraint;
4867984c4197SStefano Zampini       min_n = max_constraints;
4868984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4869674ae819SStefano Zampini         min_n = max_size_of_constraint;
4870984c4197SStefano Zampini         max_n = max_constraints;
4871674ae819SStefano Zampini       }
4872785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4873674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4874785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4875674ae819SStefano Zampini #endif
4876674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4877674ae819SStefano Zampini       lwork = -1;
4878e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4879e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4880b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4881674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4882674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
48839162d606SStefano 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));
4884674ae819SStefano Zampini #else
48859162d606SStefano 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));
4886674ae819SStefano Zampini #endif
4887674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4888984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4889984c4197SStefano Zampini #endif /* on missing GESVD */
4890674ae819SStefano Zampini       /* Allocate optimal workspace */
4891674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4892854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4893674ae819SStefano Zampini     }
4894674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4895674ae819SStefano Zampini     total_counts = 0;
48969162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
48979162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4898674ae819SStefano Zampini     /* vertices */
48999162d606SStefano Zampini     if (n_vertices) {
4900674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
49019162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4902674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
49039162d606SStefano Zampini         constraints_n[total_counts] = 1;
49049162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
49059162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
49069162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4907674ae819SStefano Zampini         total_counts++;
4908674ae819SStefano Zampini       }
4909674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4910674ae819SStefano Zampini       n_vertices = total_counts;
4911674ae819SStefano Zampini     }
4912984c4197SStefano Zampini 
4913674ae819SStefano Zampini     /* edges and faces */
49149162d606SStefano Zampini     total_counts_cc = total_counts;
4915911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
49169162d606SStefano Zampini       IS        used_is;
49179162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
49189162d606SStefano Zampini 
4919911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
49209162d606SStefano Zampini         used_is = ISForEdges[ncc];
4921984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4922674ae819SStefano Zampini       } else {
49239162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4924984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4925674ae819SStefano Zampini       }
4926674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
49279162d606SStefano Zampini 
49289162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
49299162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4930984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4931984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4932674ae819SStefano Zampini       if (nnsp_has_cnst) {
49335b08dc53SStefano Zampini         PetscScalar quad_value;
49349162d606SStefano Zampini 
49359162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
49369162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
49379162d606SStefano Zampini 
4938a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4939674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4940a773dcb8SStefano Zampini         } else {
4941a773dcb8SStefano Zampini           quad_value = 1.0;
4942a773dcb8SStefano Zampini         }
4943674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49449162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4945674ae819SStefano Zampini         }
49469162d606SStefano Zampini         temp_constraints++;
4947674ae819SStefano Zampini         total_counts++;
4948674ae819SStefano Zampini       }
4949674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4950984c4197SStefano Zampini         PetscReal real_value;
49519162d606SStefano Zampini         PetscScalar *ptr_to_data;
49529162d606SStefano Zampini 
4953984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
49549162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4955674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
49569162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4957674ae819SStefano Zampini         }
4958984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
4959984c4197SStefano Zampini         /* check if array is null on the connected component */
4960e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
49619162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
49625b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
4963674ae819SStefano Zampini           temp_constraints++;
4964674ae819SStefano Zampini           total_counts++;
49659162d606SStefano Zampini           if (!idxs_copied) {
49669162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
49679162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
4968674ae819SStefano Zampini           }
4969674ae819SStefano Zampini         }
49709162d606SStefano Zampini       }
49719162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
497245a1bb75SStefano Zampini       valid_constraints = temp_constraints;
4973eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
4974a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
49759162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
49769162d606SStefano Zampini 
49779162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4978a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
49799162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
4980a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
49819162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
4982a773dcb8SStefano Zampini         } else { /* perform SVD */
4983984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
49849162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4985674ae819SStefano Zampini 
4986674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4987984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
4988984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
4989984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
4990984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
4991984c4197SStefano Zampini                 from that computed using LAPACKgesvd
4992984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
4993984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
4994984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
4995674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
4996e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4997984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4998674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
4999674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
50009162d606SStefano 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));
5001674ae819SStefano Zampini             }
5002674ae819SStefano Zampini           }
5003e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
5004e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5005e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
5006674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
5007c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
5008674ae819SStefano Zampini #else
5009c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
5010674ae819SStefano Zampini #endif
5011674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5012984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
5013984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
5014674ae819SStefano Zampini           j = 0;
5015984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
5016674ae819SStefano Zampini           total_counts = total_counts-j;
501745a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
5018e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
5019c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5020c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5021c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
5022c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5023c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
5024c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5025674ae819SStefano Zampini           if (j<temp_constraints) {
5026984c4197SStefano Zampini             PetscInt ii;
5027984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
5028674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
50299162d606SStefano 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));
5030674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5031984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
5032674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
50339162d606SStefano 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];
5034674ae819SStefano Zampini               }
5035674ae819SStefano Zampini             }
5036674ae819SStefano Zampini           }
5037674ae819SStefano Zampini #else  /* on missing GESVD */
5038e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
5039e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
5040b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5041674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5042674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
50439162d606SStefano 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));
5044674ae819SStefano Zampini #else
50459162d606SStefano 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));
5046674ae819SStefano Zampini #endif
5047984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
5048674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5049984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
5050e310c8b4SStefano Zampini           k = temp_constraints;
5051e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
5052674ae819SStefano Zampini           j = 0;
5053e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
505445a1bb75SStefano Zampini           valid_constraints = k-j;
5055911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
5056984c4197SStefano Zampini #endif /* on missing GESVD */
5057674ae819SStefano Zampini         }
5058a773dcb8SStefano Zampini       }
50599162d606SStefano Zampini       /* update pointers information */
50609162d606SStefano Zampini       if (valid_constraints) {
50619162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
50629162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
50639162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
50649162d606SStefano Zampini         /* set change_of_basis flag */
506545a1bb75SStefano Zampini         if (boolforchange) {
5066b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
50679162d606SStefano Zampini         }
5068b3d85658SStefano Zampini         total_counts_cc++;
506945a1bb75SStefano Zampini       }
507045a1bb75SStefano Zampini     }
5071984c4197SStefano Zampini     /* free workspace */
50728f1c130eSStefano Zampini     if (!skip_lapack) {
5073984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
5074984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
5075984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
5076984c4197SStefano Zampini #endif
5077984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
5078984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
5079984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
5080984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
5081984c4197SStefano Zampini #endif
5082984c4197SStefano Zampini     }
5083984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
5084984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
5085984c4197SStefano Zampini     }
5086984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
5087cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
5088cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
5089cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
5090cf5a6209SStefano Zampini     }
5091cf5a6209SStefano Zampini     if (n_ISForFaces) {
5092cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
5093cf5a6209SStefano Zampini     }
5094cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
5095cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
5096cf5a6209SStefano Zampini     }
5097cf5a6209SStefano Zampini     if (n_ISForEdges) {
5098cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
5099cf5a6209SStefano Zampini     }
5100cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
510108122e43SStefano Zampini   } else {
510208122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
5103984c4197SStefano Zampini 
510408122e43SStefano Zampini     total_counts = 0;
510508122e43SStefano Zampini     n_vertices = 0;
5106d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
5107d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
510808122e43SStefano Zampini     }
510908122e43SStefano Zampini     max_constraints = 0;
51109162d606SStefano Zampini     total_counts_cc = 0;
511108122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
511208122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
51139162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
511408122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
511508122e43SStefano Zampini     }
51169162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
51179162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
51189162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
51199162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
512074d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
51219162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
51229162d606SStefano Zampini     total_counts_cc = 0;
51239162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
51249162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
51259162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
512608122e43SStefano Zampini       }
512708122e43SStefano Zampini     }
51289162d606SStefano Zampini #if 0
51299162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
51309162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
51319162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
51329162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
51339162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
51349162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
51359162d606SStefano Zampini       }
51369162d606SStefano Zampini       printf("\n");
51379162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
51389162d606SStefano Zampini     }
51391b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
51408bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
51411b968477SStefano Zampini     }
51421b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
51438bec7fa6SStefano 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]);
51441b968477SStefano Zampini     }
514508122e43SStefano Zampini #endif
514608122e43SStefano Zampini 
51478bec7fa6SStefano Zampini     max_size_of_constraint = 0;
51489162d606SStefano 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]);
51499162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
515008122e43SStefano Zampini     /* Change of basis */
5151b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
515208122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
515308122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
515408122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
5155b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
515608122e43SStefano Zampini         }
515708122e43SStefano Zampini       }
515808122e43SStefano Zampini     }
515908122e43SStefano Zampini   }
5160984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
51614f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
516208122e43SStefano Zampini 
51639162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
51649162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
51656c4ed002SBarry 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);
5166674ae819SStefano Zampini 
5167674ae819SStefano Zampini   /* Create constraint matrix */
5168674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
516916f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
5170984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
5171984c4197SStefano Zampini 
5172984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
5173a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
5174a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
517574d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
5176984c4197SStefano Zampini   total_primal_vertices=0;
5177b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
51789162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
51799162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
518072b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
51819162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5182b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
518364efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
51849162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
51859162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5186a717540cSStefano Zampini       }
5187b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
518891af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5189a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5190a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5191a717540cSStefano Zampini       }
5192fa434743SStefano Zampini     } else {
5193b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5194fa434743SStefano Zampini     }
5195a717540cSStefano Zampini   }
5196b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5197b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5198674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
519970022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5200b3d85658SStefano Zampini 
52014f1b2e48SStefano 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);
52020e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
52030e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5204984c4197SStefano Zampini 
5205984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
520674d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5207785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5208984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
520974d5cdf7SStefano Zampini 
5210984c4197SStefano Zampini   j = total_primal_vertices;
521174d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5212b3d85658SStefano Zampini   cum = total_primal_vertices;
52139162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52144641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5215b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5216b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5217b3d85658SStefano Zampini       cum++;
52189162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
521974d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
522074d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
522174d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
522274d5cdf7SStefano Zampini       }
52239162d606SStefano Zampini       j += constraints_n[i];
5224674ae819SStefano Zampini     }
5225674ae819SStefano Zampini   }
5226674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5227674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5228088faed8SStefano Zampini 
5229674ae819SStefano Zampini   /* set values in constraint matrix */
5230984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
52310e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5232674ae819SStefano Zampini   }
5233984c4197SStefano Zampini   total_counts = total_primal_vertices;
52349162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
52354641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
52369162d606SStefano Zampini       PetscInt *cols;
52379162d606SStefano Zampini 
52389162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
52399162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
52409162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
52419162d606SStefano Zampini         PetscInt    row = total_counts+k;
52429162d606SStefano Zampini         PetscScalar *vals;
52439162d606SStefano Zampini 
52449162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
52459162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
52469162d606SStefano Zampini       }
52479162d606SStefano Zampini       total_counts += constraints_n[i];
5248674ae819SStefano Zampini     }
5249674ae819SStefano Zampini   }
5250674ae819SStefano Zampini   /* assembling */
5251674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5252674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5253088faed8SStefano Zampini 
5254984c4197SStefano Zampini   /*
52556a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5256984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5257f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5258984c4197SStefano Zampini   */
5259674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5260674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5261026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5262984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5263984c4197SStefano Zampini     /* working stuff for GEQRF */
526481d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5265984c4197SStefano Zampini     PetscBLASInt lqr_work;
5266984c4197SStefano Zampini     /* working stuff for UNGQR */
5267984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5268984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5269984c4197SStefano Zampini     /* working stuff for TRTRS */
5270984c4197SStefano Zampini     PetscScalar  *trs_rhs;
52713f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5272984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5273984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5274984c4197SStefano Zampini     PetscScalar  *start_vals;
5275984c4197SStefano Zampini     /* working stuff for values insertion */
52764641a718SStefano Zampini     PetscBT      is_primal;
527764efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5278906d46d4SStefano Zampini     /* matrix sizes */
5279906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5280906d46d4SStefano Zampini     /* temporary change of basis */
5281906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5282cf5a6209SStefano Zampini     /* extra space for debugging */
5283cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5284984c4197SStefano Zampini 
5285906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5286906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
528716f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5288bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5289906d46d4SStefano Zampini     /* nonzeros for local mat */
5290bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
52911dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5292bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
52931dd7afcfSStefano Zampini     } else {
52941dd7afcfSStefano Zampini       const PetscInt *ii;
52951dd7afcfSStefano Zampini       PetscInt       n;
52961dd7afcfSStefano Zampini       PetscBool      flg_row;
52971dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
52981dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
52991dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
53001dd7afcfSStefano Zampini     }
53019162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5302a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
53039162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5304a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
53059162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5306a717540cSStefano Zampini         } else {
53079162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
53089162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5309a717540cSStefano Zampini         }
5310a717540cSStefano Zampini       }
5311a717540cSStefano Zampini     }
5312906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5313bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
53141dd7afcfSStefano Zampini     /* Set interior change in the matrix */
53151dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5316bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5317906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5318a717540cSStefano Zampini       }
53191dd7afcfSStefano Zampini     } else {
53201dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
53211dd7afcfSStefano Zampini       PetscScalar    *aa;
53221dd7afcfSStefano Zampini       PetscInt       n;
53231dd7afcfSStefano Zampini       PetscBool      flg_row;
53241dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53251dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53261dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
53271dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
53281dd7afcfSStefano Zampini       }
53291dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
53301dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
53311dd7afcfSStefano Zampini     }
5332a717540cSStefano Zampini 
5333a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5334a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5335a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5336a717540cSStefano Zampini     }
5337a717540cSStefano Zampini 
5338a717540cSStefano Zampini 
5339a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5340a717540cSStefano Zampini     /*
5341a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5342a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5343a717540cSStefano Zampini 
5344a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5345a717540cSStefano Zampini 
5346a6b551f4SStefano 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)
5347a6b551f4SStefano Zampini 
5348a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5349a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5350a717540cSStefano Zampini             |              ...                        |
5351a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5352a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5353a717540cSStefano Zampini 
5354a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5355a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5356a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5357a6b551f4SStefano Zampini 
5358a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5359a717540cSStefano Zampini     */
5360a717540cSStefano Zampini     if (qr_needed) {
5361984c4197SStefano Zampini       /* space to store Q */
5362854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
53634e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
53644e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5365984c4197SStefano Zampini       /* first we issue queries for optimal work */
53663f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
53673f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
53683f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5369984c4197SStefano Zampini       lqr_work = -1;
53703f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5371984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5372984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5373785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5374984c4197SStefano Zampini       lgqr_work = -1;
53753f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
53763f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
53773f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
53783f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
53793f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
53803f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5381984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5382984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5383785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5384984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5385785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5386a717540cSStefano Zampini       /* allocating workspace for check */
5387a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5388cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5389a717540cSStefano Zampini       }
5390a717540cSStefano Zampini     }
5391984c4197SStefano Zampini     /* array to store whether a node is primal or not */
53924641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5393473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
53940e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
53956c4ed002SBarry 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);
539639e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
539739e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
539839e2fb2aSStefano Zampini     }
539939e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5400984c4197SStefano Zampini 
5401a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
54029162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
54039162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
54044641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5405984c4197SStefano Zampini         /* get constraint info */
54069162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5407984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5408984c4197SStefano Zampini 
5409984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
54109162d606SStefano 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);
5411674ae819SStefano Zampini         }
5412984c4197SStefano Zampini 
5413fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5414a717540cSStefano Zampini 
5415a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5416a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
54179162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5418a717540cSStefano Zampini           }
5419984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
54209162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5421984c4197SStefano Zampini 
5422984c4197SStefano Zampini           /* compute QR decomposition of constraints */
54233f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54243f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5426674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54273f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5428984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5429674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5430984c4197SStefano Zampini 
5431984c4197SStefano Zampini           /* explictly compute R^-T */
5432984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5433984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
54343f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54353f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
54363f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54373f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5438984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54393f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5440984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5441984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5442984c4197SStefano Zampini 
5443a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
54443f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
54463f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54473f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5448984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54493f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5450984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5451984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5452984c4197SStefano Zampini 
5453984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5454984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5455984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
54563f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
54573f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
54583f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
54593f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
54603f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
54613f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5462984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
54639162d606SStefano 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));
5464984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
54659162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5466984c4197SStefano Zampini 
5467984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
54689162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5469984c4197SStefano Zampini           /* insert cols for primal dofs */
5470984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5471984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
54729162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5473906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5474984c4197SStefano Zampini           }
5475984c4197SStefano Zampini           /* insert cols for dual dofs */
5476984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
54779162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5478984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
54799162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5480906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5481984c4197SStefano Zampini               j++;
5482674ae819SStefano Zampini             }
5483674ae819SStefano Zampini           }
5484984c4197SStefano Zampini 
5485984c4197SStefano Zampini           /* check change of basis */
5486984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5487984c4197SStefano Zampini             PetscInt   ii,jj;
5488984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5489c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5490c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5491c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5492c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5493c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5494c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5495984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5496cf5a6209SStefano 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));
5497984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5498984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5499984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5500cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5501cf5a6209SStefano 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;
5502674ae819SStefano Zampini               }
5503674ae819SStefano Zampini             }
5504984c4197SStefano Zampini             if (!valid_qr) {
550522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5506984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5507984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5508cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5509cf5a6209SStefano 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]));
5510674ae819SStefano Zampini                   }
5511cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5512cf5a6209SStefano 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]));
5513984c4197SStefano Zampini                   }
5514984c4197SStefano Zampini                 }
5515984c4197SStefano Zampini               }
5516674ae819SStefano Zampini             } else {
551722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5518674ae819SStefano Zampini             }
5519674ae819SStefano Zampini           }
5520a717540cSStefano Zampini         } else { /* simple transformation block */
5521a717540cSStefano Zampini           PetscInt    row,col;
5522a6b551f4SStefano Zampini           PetscScalar val,norm;
5523a6b551f4SStefano Zampini 
5524a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
55259162d606SStefano 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));
5526a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
55279162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
55289162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5529bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
55309162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5531906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
55329162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5533a717540cSStefano Zampini             } else {
5534a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
55359162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5536a717540cSStefano Zampini                 if (row != col) {
55379162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5538a717540cSStefano Zampini                 } else {
55399162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5540a717540cSStefano Zampini                 }
5541906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5542a717540cSStefano Zampini               }
5543a717540cSStefano Zampini             }
5544a717540cSStefano Zampini           }
554598a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
554622d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5547a717540cSStefano Zampini           }
5548674ae819SStefano Zampini         }
5549984c4197SStefano Zampini       } else {
5550984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
55519162d606SStefano 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);
5552674ae819SStefano Zampini         }
5553674ae819SStefano Zampini       }
5554674ae819SStefano Zampini     }
5555a717540cSStefano Zampini 
5556a717540cSStefano Zampini     /* free workspace */
5557a717540cSStefano Zampini     if (qr_needed) {
5558984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5559cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5560984c4197SStefano Zampini       }
5561984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5562984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5563984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5564984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5565984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5566674ae819SStefano Zampini     }
5567a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5568906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5569906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5570906d46d4SStefano Zampini 
5571906d46d4SStefano Zampini     /* assembling of global change of variable */
557288c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5573bbb9e6c6SStefano Zampini       Mat      tmat;
557416f15bc4SStefano Zampini       PetscInt bs;
557516f15bc4SStefano Zampini 
5576906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5577906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5578bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5579bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5580bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5581bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
558216f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
558316f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5584906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5585bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5586bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5587bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5588bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5589bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5590e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5591e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5592bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5593bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
559488c03ad3SStefano Zampini 
5595906d46d4SStefano Zampini       /* check */
5596906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5597906d46d4SStefano Zampini         PetscReal error;
5598906d46d4SStefano Zampini         Vec       x,x_change;
5599906d46d4SStefano Zampini 
5600906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5601906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5602906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5603906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5604e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5605e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5606bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5607e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5608e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5609906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5610906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5611906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5612906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5613bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5614906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5615906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5616906d46d4SStefano Zampini       }
5617b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5618b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5619b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5620bf3a8328SStefano Zampini 
56219a962809SStefano 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);
5622b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5623ac632422SStefano Zampini           Mat                    S_new,tmat;
5624bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5625bbb9e6c6SStefano Zampini 
5626bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
56276816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5628bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5629bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5630bf3a8328SStefano Zampini             IS                     is_V;
5631b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5632b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5633b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5634b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5635b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5636bf3a8328SStefano Zampini           }
5637bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5638ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5639b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5640ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5641bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5642bf3a8328SStefano Zampini             const PetscScalar *array;
5643bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5644bf3a8328SStefano Zampini             PetscInt          i,n_V;
5645bf3a8328SStefano Zampini 
5646b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5647b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5648b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5649b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5650b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5651b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5652b087196eSStefano Zampini               PetscScalar val;
5653b087196eSStefano Zampini               PetscInt    idx;
5654b087196eSStefano Zampini 
5655b087196eSStefano Zampini               idx = idxs_V[i];
5656b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5657b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5658b087196eSStefano Zampini             }
5659b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5660b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5661bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5662bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5663bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5664bf3a8328SStefano Zampini           }
5665ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5666ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5667ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5668ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5669b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5670ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5671bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5672b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5673bf3a8328SStefano Zampini             }
5674ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5675ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5676ac632422SStefano Zampini           }
5677b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
567888c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5679b96c3477SStefano Zampini         }
5680c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5681b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5682c9db6a07SStefano Zampini           PetscInt i;
5683c9db6a07SStefano Zampini 
5684c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5685c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5686c9db6a07SStefano Zampini           }
5687c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5688c9db6a07SStefano Zampini         }
5689b96c3477SStefano Zampini       }
569016909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
569116909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
569216909a7fSStefano Zampini       } else {
5693906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
569416909a7fSStefano Zampini       }
56951dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
569627b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
569772b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
569872b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
569972b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
570072b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
570172b8c272SStefano Zampini     }
57021dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
570327b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5704b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5705b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5706906d46d4SStefano Zampini     } else {
57071dd7afcfSStefano Zampini       Mat benign_global = NULL;
570827b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
57091dd7afcfSStefano Zampini         Mat tmat;
57101dd7afcfSStefano Zampini 
57111dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
57121dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
57131dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
57141dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57151dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
57161dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
57171dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57181dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57191dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
57201dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
57211dd7afcfSStefano Zampini           Mat M;
57221dd7afcfSStefano Zampini 
57231dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
57241dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
57251dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
57261dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5727906d46d4SStefano Zampini         } else {
57281dd7afcfSStefano Zampini           Mat         eye;
57291dd7afcfSStefano Zampini           PetscScalar *array;
57301dd7afcfSStefano Zampini 
57311dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57321dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
57331dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
57341dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5735906d46d4SStefano Zampini           }
57361dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
57371dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57381dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57391dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
57401dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
57411dd7afcfSStefano Zampini         }
57421dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
57431dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
57441dd7afcfSStefano Zampini       }
57451dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
57461dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
57471dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
574827b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
57491dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
57501dd7afcfSStefano Zampini       }
57511dd7afcfSStefano Zampini     }
575216909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
575316909a7fSStefano Zampini       IS             is_global;
575416909a7fSStefano Zampini       const PetscInt *gidxs;
575516909a7fSStefano Zampini 
575616909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
575716909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
575816909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
575916909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
576016909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
576116909a7fSStefano Zampini     }
57621dd7afcfSStefano Zampini   }
57631dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
57641dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5765b9b85e73SStefano Zampini   }
5766a717540cSStefano Zampini 
576772b8c272SStefano Zampini   if (!pcbddc->fake_change) {
57684f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
57694f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
57704f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
57714f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5772019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5773019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5774019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5775019a44ceSStefano Zampini     }
5776019a44ceSStefano Zampini 
5777019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5778727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5779727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
57809f47a83aSStefano 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);
5781c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
57820e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
57839f47a83aSStefano 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);
5784727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5785727cdba6SStefano Zampini       }
57860e6343abSStefano Zampini     }
5787727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5788b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
578972b8c272SStefano Zampini   }
579072b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5791727cdba6SStefano Zampini 
5792a717540cSStefano Zampini   /* flush dbg viewer */
5793b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5794b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5795b8ffe317SStefano Zampini   }
5796a717540cSStefano Zampini 
5797e310c8b4SStefano Zampini   /* free workspace */
5798a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
57994641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
580008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
58019162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
58029162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
580308122e43SStefano Zampini   } else {
58049162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
58059162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
58069162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
580708122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
580808122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
58099162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
58109162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
581108122e43SStefano Zampini   }
5812674ae819SStefano Zampini   PetscFunctionReturn(0);
5813674ae819SStefano Zampini }
5814674ae819SStefano Zampini 
5815674ae819SStefano Zampini #undef __FUNCT__
5816674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5817674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5818674ae819SStefano Zampini {
581971582508SStefano Zampini   ISLocalToGlobalMapping map;
5820674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5821674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
582214f95afaSStefano Zampini   PetscInt               ierr,i,N;
5823674ae819SStefano Zampini 
5824674ae819SStefano Zampini   PetscFunctionBegin;
5825c8272957SStefano Zampini   if (pcbddc->graphanalyzed && !pcbddc->recompute_topography) PetscFunctionReturn(0);
58268e61c736SStefano Zampini   /* Reset previously computed graph */
58278e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5828674ae819SStefano Zampini   /* Init local Graph struct */
58297fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
583071582508SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5831be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5832674ae819SStefano Zampini 
5833575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
58349a962809SStefano 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);
58359577ea80SStefano Zampini 
5836674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5837d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
58384d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
58394d379d7bSStefano Zampini     PetscInt  nvtxs;
5840e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
5841674ae819SStefano Zampini 
58422fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
58432fffb893SStefano Zampini     if (flg_row) {
58444d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5845b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
58462fffb893SStefano Zampini     }
58472fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5848674ae819SStefano Zampini   }
58499b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
58509b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5851674ae819SStefano Zampini   }
5852674ae819SStefano Zampini 
5853674ae819SStefano Zampini   /* Setup of Graph */
58544b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
585514f95afaSStefano 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);
5856674ae819SStefano Zampini 
58574f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
58584f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
58594f1b2e48SStefano Zampini     PetscInt *local_subs;
58604f1b2e48SStefano Zampini 
58614f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
58624f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
58634f1b2e48SStefano Zampini       const PetscInt *idxs;
58644f1b2e48SStefano Zampini       PetscInt       nl,j;
58654f1b2e48SStefano Zampini 
58664f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
58674f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
586871582508SStefano Zampini       for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
58694f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
58704f1b2e48SStefano Zampini     }
58714f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
58724f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
58734f1b2e48SStefano Zampini   }
58744f1b2e48SStefano Zampini 
5875674ae819SStefano Zampini   /* Graph's connected components analysis */
5876674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
587771582508SStefano Zampini 
587871582508SStefano Zampini   /* set flag indicating analysis has been done */
587971582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_TRUE;
5880674ae819SStefano Zampini   PetscFunctionReturn(0);
5881674ae819SStefano Zampini }
5882674ae819SStefano Zampini 
58839a7d3425SStefano Zampini #undef __FUNCT__
58849a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
58859a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
58869a7d3425SStefano Zampini {
58879a7d3425SStefano Zampini   PetscInt       i,j;
58889a7d3425SStefano Zampini   PetscScalar    *alphas;
58899a7d3425SStefano Zampini   PetscErrorCode ierr;
58909a7d3425SStefano Zampini 
58919a7d3425SStefano Zampini   PetscFunctionBegin;
5892785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
58939a7d3425SStefano Zampini   for (i=0;i<n;i++) {
58949a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5895669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5896669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5897669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
58989a7d3425SStefano Zampini   }
58999a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
59009a7d3425SStefano Zampini   PetscFunctionReturn(0);
59019a7d3425SStefano Zampini }
59029a7d3425SStefano Zampini 
5903e7931f94SStefano Zampini #undef __FUNCT__
590470cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
590557de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5906e7931f94SStefano Zampini {
590757de7509SStefano Zampini   Mat            A;
5908e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5909e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
591052e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
591152e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
591227b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
591357de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
591427b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
591527b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
591627b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
591727b6a85dSStefano Zampini   MPI_Comm       subcomm;
591852e5ac9dSStefano Zampini   PetscErrorCode ierr;
5919a57a6d2fSStefano Zampini 
5920e7931f94SStefano Zampini   PetscFunctionBegin;
592157de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
592257de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
592357de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
592457de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
592557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
592657de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
592757de7509SStefano Zampini 
592857de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
592957de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
593057de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
593157de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
593257de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
593357de7509SStefano Zampini   im_active = !!(n);
593457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
593557de7509SStefano Zampini   void_procs = size - active_procs;
593657de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
593757de7509SStefano Zampini   if (void_procs) {
593857de7509SStefano Zampini     PetscInt ncand;
593957de7509SStefano Zampini 
594057de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
594157de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
594257de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
594357de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
594457de7509SStefano Zampini       if (!procs_candidates[i]) {
594557de7509SStefano Zampini         procs_candidates[ncand++] = i;
594657de7509SStefano Zampini       }
594757de7509SStefano Zampini     }
594857de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
594957de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
595057de7509SStefano Zampini   }
595157de7509SStefano Zampini 
595214f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
595314f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
595414f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
595514f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
595614f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
595714f0bfb9SStefano Zampini     else dest = rank;
595857de7509SStefano Zampini     if (im_active) {
595957de7509SStefano Zampini       issize = 1;
596057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
596114f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
596257de7509SStefano Zampini       } else {
596314f0bfb9SStefano Zampini         isidx = dest;
596457de7509SStefano Zampini       }
596557de7509SStefano Zampini     } else {
596657de7509SStefano Zampini       issize = 0;
596757de7509SStefano Zampini       isidx = -1;
596857de7509SStefano Zampini     }
596957de7509SStefano Zampini     *n_subdomains = active_procs;
597057de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
5971daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
597257de7509SStefano Zampini     PetscFunctionReturn(0);
597357de7509SStefano Zampini   }
5974c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
5975c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
597627b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
5977e7931f94SStefano Zampini 
5978e7931f94SStefano Zampini   /* Get info on mapping */
59793bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
59803bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5981e7931f94SStefano Zampini 
5982e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
5983785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
5984e7931f94SStefano Zampini   xadj[0] = 0;
5985e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
5986785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
5987785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
598827b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
598927b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
599027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
599127b6a85dSStefano Zampini       count[shared[i][j]] += 1;
5992e7931f94SStefano Zampini 
599327b6a85dSStefano Zampini   xadj_count = 0;
59942b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
599527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
599627b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
5997d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
5998d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
5999d023bfaeSStefano Zampini         xadj_count++;
600027b6a85dSStefano Zampini         break;
600127b6a85dSStefano Zampini       }
6002e7931f94SStefano Zampini     }
6003e7931f94SStefano Zampini   }
6004d023bfaeSStefano Zampini   xadj[1] = xadj_count;
600527b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
60063bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
6007e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
6008e7931f94SStefano Zampini 
60093837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
6010e7931f94SStefano Zampini 
601127b6a85dSStefano Zampini   /* Restrict work on active processes only */
601227b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
601327b6a85dSStefano Zampini   if (void_procs) {
601427b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
601527b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
601627b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
601727b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
601827b6a85dSStefano Zampini   } else {
601927b6a85dSStefano Zampini     psubcomm = NULL;
602027b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
602127b6a85dSStefano Zampini   }
602227b6a85dSStefano Zampini 
602327b6a85dSStefano Zampini   v_wgt = NULL;
602427b6a85dSStefano Zampini   if (!color) {
6025e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
6026e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
6027e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6028c8587f34SStefano Zampini   } else {
602952e5ac9dSStefano Zampini     Mat             subdomain_adj;
603052e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
603152e5ac9dSStefano Zampini     MatPartitioning partitioner;
603227b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
603352e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
603457de7509SStefano Zampini     PetscMPIInt     size;
6035b0c7d250SStefano Zampini     PetscBool       aggregate;
6036b0c7d250SStefano Zampini 
603727b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
603827b6a85dSStefano Zampini     if (void_procs) {
603927b6a85dSStefano Zampini       PetscInt prank = rank;
6040785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
604127b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
6042e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
6043e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
6044c8587f34SStefano Zampini       }
6045e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
604627b6a85dSStefano Zampini     } else {
604727b6a85dSStefano Zampini       oldranks = NULL;
604827b6a85dSStefano Zampini     }
6049b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
605027b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
6051b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
6052b0c7d250SStefano Zampini       PetscMPIInt nrank;
6053b0c7d250SStefano Zampini       PetscScalar *vals;
6054b0c7d250SStefano Zampini 
605527b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
6056b0c7d250SStefano Zampini       lrows = 0;
6057b0c7d250SStefano Zampini       if (nrank<redprocs) {
6058b0c7d250SStefano Zampini         lrows = size/redprocs;
6059b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
6060b0c7d250SStefano Zampini       }
606127b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
6062b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
6063b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6064b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
6065b0c7d250SStefano Zampini       row = nrank;
6066b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
6067b0c7d250SStefano Zampini       cols = adjncy;
6068b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
6069b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
6070b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
6071b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6072b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
607352e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
607452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
607552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
6076b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
607727b6a85dSStefano Zampini       if (use_vwgt) {
607827b6a85dSStefano Zampini         Vec               v;
607927b6a85dSStefano Zampini         const PetscScalar *array;
608027b6a85dSStefano Zampini         PetscInt          nl;
608127b6a85dSStefano Zampini 
608227b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
608327b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
608427b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
608527b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
608627b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
608727b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
608827b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
608922db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
609027b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
609127b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
609227b6a85dSStefano Zampini       }
6093b0c7d250SStefano Zampini     } else {
609427b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
609527b6a85dSStefano Zampini       if (use_vwgt) {
609627b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
609727b6a85dSStefano Zampini         v_wgt[0] = local_size;
609827b6a85dSStefano Zampini       }
6099b0c7d250SStefano Zampini     }
610022b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
6101e7931f94SStefano Zampini 
6102e7931f94SStefano Zampini     /* Partition */
610327b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
6104e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
610527b6a85dSStefano Zampini     if (v_wgt) {
6106e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
6107c8587f34SStefano Zampini     }
610857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
610957de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
6110e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
6111e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
611222b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
6113e7931f94SStefano Zampini 
611452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
61156583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
611652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
611752e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
611857de7509SStefano Zampini     if (!aggregate) {
611957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
612027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
612127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
612227b6a85dSStefano Zampini #endif
612357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
612427b6a85dSStefano Zampini       } else if (oldranks) {
6125b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
612627b6a85dSStefano Zampini       } else {
612727b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
612857de7509SStefano Zampini       }
612928143c3dSStefano Zampini     } else {
6130b0c7d250SStefano Zampini       PetscInt    idxs[1];
6131b0c7d250SStefano Zampini       PetscMPIInt tag;
6132b0c7d250SStefano Zampini       MPI_Request *reqs;
6133b0c7d250SStefano Zampini 
6134b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
6135b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
6136b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
613727b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
613828143c3dSStefano Zampini       }
613927b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
6140b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6141b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
614257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
614327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
614427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
614527b6a85dSStefano Zampini #endif
614657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
614727b6a85dSStefano Zampini       } else if (oldranks) {
6148b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
614927b6a85dSStefano Zampini       } else {
615027b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
6151e7931f94SStefano Zampini       }
615257de7509SStefano Zampini     }
615352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6154e7931f94SStefano Zampini     /* clean up */
6155e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
615652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
6157e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
6158e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
6159e7931f94SStefano Zampini   }
616027b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
616157de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
6162e7931f94SStefano Zampini 
6163e7931f94SStefano Zampini   /* assemble parallel IS for sends */
6164e7931f94SStefano Zampini   i = 1;
616527b6a85dSStefano Zampini   if (!color) i=0;
616657de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
6167e7931f94SStefano Zampini   PetscFunctionReturn(0);
6168e7931f94SStefano Zampini }
6169e7931f94SStefano Zampini 
6170e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
6171e7931f94SStefano Zampini 
6172e7931f94SStefano Zampini #undef __FUNCT__
6173e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
61741ae86dd6SStefano 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[])
6175e7931f94SStefano Zampini {
617670cf5478SStefano Zampini   Mat                    local_mat;
6177e7931f94SStefano Zampini   IS                     is_sends_internal;
61789d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
61791ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
61809d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6181e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6182e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6183e7931f94SStefano Zampini   const PetscInt*        is_indices;
6184e7931f94SStefano Zampini   MatType                new_local_type;
6185e7931f94SStefano Zampini   /* buffers */
6186e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
618728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
61889d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6189e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
61901ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6191e7931f94SStefano Zampini   /* MPI */
619228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
619328143c3dSStefano Zampini   PetscSubcomm           subcomm;
6194e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
619528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
619628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
61971ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
61981ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
61991ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6200e7931f94SStefano Zampini   PetscErrorCode         ierr;
6201e7931f94SStefano Zampini 
6202e7931f94SStefano Zampini   PetscFunctionBegin;
620357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6204e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
620528143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
620657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
620757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
620857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
620957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
621057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
62111ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
62121ae86dd6SStefano Zampini   if (nvecs) {
62131ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
62141ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
62151ae86dd6SStefano Zampini   }
621657de7509SStefano Zampini   /* further checks */
6217e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6218e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6219e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6220e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6221e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
622257de7509SStefano Zampini   if (reuse && *mat_n) {
622370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
622457de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
622570cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
622628143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
622770cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
622870cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
622970cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
623070cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
623170cf5478SStefano Zampini   }
6232e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6233e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
623457de7509SStefano Zampini 
6235e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6236e7931f94SStefano Zampini   if (!is_sends) {
623728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
623857de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6239c8587f34SStefano Zampini   } else {
6240e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6241e7931f94SStefano Zampini     is_sends_internal = is_sends;
6242c8587f34SStefano Zampini   }
6243e7931f94SStefano Zampini 
6244e7931f94SStefano Zampini   /* get comm */
6245a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6246e7931f94SStefano Zampini 
6247e7931f94SStefano Zampini   /* compute number of sends */
6248e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6249e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6250e7931f94SStefano Zampini 
6251e7931f94SStefano Zampini   /* compute number of receives */
6252e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6253785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6254e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6255e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6256e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6257e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6258e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6259e7931f94SStefano Zampini 
626028143c3dSStefano Zampini   /* restrict comm if requested */
626128143c3dSStefano Zampini   subcomm = 0;
626228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
626328143c3dSStefano Zampini   if (restrict_comm) {
6264779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6265779c1cceSStefano Zampini 
626628143c3dSStefano Zampini     color = 0;
626753a05cb3SStefano Zampini     if (restrict_full) {
626853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
626953a05cb3SStefano Zampini     } else {
627053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
627153a05cb3SStefano Zampini     }
6272b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
627328143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
627428143c3dSStefano Zampini     /* check if reuse has been requested */
627557de7509SStefano Zampini     if (reuse) {
627628143c3dSStefano Zampini       if (*mat_n) {
627728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
627828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
627928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
628028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
628128143c3dSStefano Zampini       } else {
628228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
628328143c3dSStefano Zampini       }
628428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6285779c1cceSStefano Zampini       PetscMPIInt rank;
6286779c1cceSStefano Zampini 
6287779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
628828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
628928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
629028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6291306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
629228143c3dSStefano Zampini     }
629328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
629428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
629528143c3dSStefano Zampini   } else {
629628143c3dSStefano Zampini     comm_n = comm;
629728143c3dSStefano Zampini   }
629828143c3dSStefano Zampini 
6299e7931f94SStefano Zampini   /* prepare send/receive buffers */
6300785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6301e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6302785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6303e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
630428143c3dSStefano Zampini   if (nis) {
6305854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
630628143c3dSStefano Zampini   }
6307e7931f94SStefano Zampini 
630828143c3dSStefano Zampini   /* Get data from local matrices */
63096c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6310e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6311e7931f94SStefano Zampini     /*
6312e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6313e7931f94SStefano Zampini        send_buffer_idxs should contain:
6314e7931f94SStefano Zampini        - MatType_PRIVATE type
6315e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6316e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6317e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6318e7931f94SStefano Zampini     */
63196c4ed002SBarry Smith   else {
6320e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
63213bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6322854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6323e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6324e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
63253bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6326e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
63273bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6328e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6329e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6330e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6331e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6332c8587f34SStefano Zampini     }
6333c8587f34SStefano Zampini   }
6334e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
633528143c3dSStefano Zampini   /* additional is (if any) */
633628143c3dSStefano Zampini   if (nis) {
633728143c3dSStefano Zampini     PetscMPIInt psum;
633828143c3dSStefano Zampini     PetscInt j;
633928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
634028143c3dSStefano Zampini       PetscInt plen;
634128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
634228143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
634328143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
634428143c3dSStefano Zampini     }
6345854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
634628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
634728143c3dSStefano Zampini       PetscInt plen;
634828143c3dSStefano Zampini       const PetscInt *is_array_idxs;
634928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
635028143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
635128143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
635228143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
635328143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
635428143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
635528143c3dSStefano Zampini     }
635628143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
635728143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
635828143c3dSStefano Zampini     }
635928143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
636028143c3dSStefano Zampini   }
636128143c3dSStefano Zampini 
6362e7931f94SStefano Zampini   buf_size_idxs = 0;
6363e7931f94SStefano Zampini   buf_size_vals = 0;
636428143c3dSStefano Zampini   buf_size_idxs_is = 0;
63651ae86dd6SStefano Zampini   buf_size_vecs = 0;
6366e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6367e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6368e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
636928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
63701ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6371e7931f94SStefano Zampini   }
6372785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6373785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
637495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
63751ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6376e7931f94SStefano Zampini 
6377e7931f94SStefano Zampini   /* get new tags for clean communications */
6378e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6379e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
638028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
63811ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6382e7931f94SStefano Zampini 
6383e7931f94SStefano Zampini   /* allocate for requests */
6384785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6385785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
638695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
63871ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6388785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6389785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
639095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
63911ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6392e7931f94SStefano Zampini 
6393e7931f94SStefano Zampini   /* communications */
6394e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6395e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
639628143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
63971ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6398e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6399e7931f94SStefano Zampini     source_dest = onodes[i];
6400e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6401e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6402e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6403e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
640428143c3dSStefano Zampini     if (nis) {
640557de7509SStefano Zampini       source_dest = onodes_is[i];
640628143c3dSStefano 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);
640728143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
640828143c3dSStefano Zampini     }
64091ae86dd6SStefano Zampini     if (nvecs) {
64101ae86dd6SStefano Zampini       source_dest = onodes[i];
64111ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
64121ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
64131ae86dd6SStefano Zampini     }
6414e7931f94SStefano Zampini   }
6415e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6416e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6417e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6418e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
641928143c3dSStefano Zampini     if (nis) {
642028143c3dSStefano 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);
642128143c3dSStefano Zampini     }
64221ae86dd6SStefano Zampini     if (nvecs) {
64231ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64241ae86dd6SStefano 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);
64251ae86dd6SStefano Zampini     }
6426e7931f94SStefano Zampini   }
6427e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6428e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6429e7931f94SStefano Zampini 
6430e7931f94SStefano Zampini   /* assemble new l2g map */
6431e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6432e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64339d30be91SStefano Zampini   new_local_rows = 0;
6434e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64359d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6436e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6437e7931f94SStefano Zampini   }
64389d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6439e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
64409d30be91SStefano Zampini   new_local_rows = 0;
6441e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
64429d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
64439d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6444e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6445e7931f94SStefano Zampini   }
64469d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
64479d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6448e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6449e7931f94SStefano Zampini 
6450e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6451e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6452e7931f94SStefano 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) */
6453e7931f94SStefano Zampini   if (n_recvs) {
645428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6455e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6456e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6457e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6458e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6459e7931f94SStefano Zampini         break;
6460e7931f94SStefano Zampini       }
6461e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6462e7931f94SStefano Zampini     }
6463e7931f94SStefano Zampini     switch (new_local_type_private) {
646428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
646528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6466e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6467e7931f94SStefano Zampini           bs = 1;
646828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
646928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
647028143c3dSStefano Zampini           bs = 1;
647128143c3dSStefano Zampini         }
6472e7931f94SStefano Zampini         break;
6473e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6474e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6475e7931f94SStefano Zampini         bs = 1;
6476e7931f94SStefano Zampini         break;
6477e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6478e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6479e7931f94SStefano Zampini         break;
6480e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6481e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6482e7931f94SStefano Zampini         break;
6483e7931f94SStefano Zampini       default:
64849d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6485e7931f94SStefano Zampini         break;
6486e7931f94SStefano Zampini     }
648728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
648828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
648928143c3dSStefano Zampini     bs = 1;
6490e7931f94SStefano Zampini   }
6491e7931f94SStefano Zampini 
649270cf5478SStefano Zampini   /* create MATIS object if needed */
649357de7509SStefano Zampini   if (!reuse) {
6494e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6495e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
649670cf5478SStefano Zampini   } else {
649770cf5478SStefano Zampini     /* it also destroys the local matrices */
649857de7509SStefano Zampini     if (*mat_n) {
649970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
650057de7509SStefano Zampini     } else { /* this is a fake object */
650157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
650257de7509SStefano Zampini     }
650370cf5478SStefano Zampini   }
650470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6505e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
65069d30be91SStefano Zampini 
65079d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
65089d30be91SStefano Zampini 
65099d30be91SStefano Zampini   /* Global to local map of received indices */
65109d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
65119d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
65129d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
65139d30be91SStefano Zampini 
65149d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
65159d30be91SStefano Zampini   buf_size_idxs = 0;
65169d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
65179d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
65189d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
65199d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
65209d30be91SStefano Zampini   }
65219d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
65229d30be91SStefano Zampini 
65239d30be91SStefano Zampini   /* set preallocation */
65249d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
65259d30be91SStefano Zampini   if (!newisdense) {
65269d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
65279d30be91SStefano Zampini 
65289d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
65299d30be91SStefano Zampini     if (n_recvs) {
65309d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
65319d30be91SStefano Zampini     }
65329d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
65339d30be91SStefano Zampini       PetscInt j;
65349d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
65359d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
65369d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
65379d30be91SStefano Zampini         }
65389d30be91SStefano Zampini       } else {
65399d30be91SStefano Zampini         /* TODO */
65409d30be91SStefano Zampini       }
65419d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
65429d30be91SStefano Zampini     }
65439d30be91SStefano Zampini     if (new_local_nnz) {
65449d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
65459d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
65469d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
65479d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65489d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
65499d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
65509d30be91SStefano Zampini     } else {
65519d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65529d30be91SStefano Zampini     }
65539d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
65549d30be91SStefano Zampini   } else {
65559d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
65569d30be91SStefano Zampini   }
6557e7931f94SStefano Zampini 
6558e7931f94SStefano Zampini   /* set values */
6559e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
65609d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6561e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6562e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6563e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
65649d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6565e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6566e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6567e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
656828143c3dSStefano Zampini     } else {
656928143c3dSStefano Zampini       /* TODO */
6570e7931f94SStefano Zampini     }
6571e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6572e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6573e7931f94SStefano Zampini   }
6574e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6575e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
657670cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
657770cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65789d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6579e7931f94SStefano Zampini 
6580dfd14d43SStefano Zampini #if 0
658128143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6582e7931f94SStefano Zampini     Vec       lvec,rvec;
6583e7931f94SStefano Zampini     PetscReal infty_error;
6584e7931f94SStefano Zampini 
65852a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6586e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6587e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6588e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
658970cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6590e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6591e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6592e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6593e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6594e7931f94SStefano Zampini   }
659528143c3dSStefano Zampini #endif
6596e7931f94SStefano Zampini 
659728143c3dSStefano Zampini   /* assemble new additional is (if any) */
659828143c3dSStefano Zampini   if (nis) {
659928143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
660028143c3dSStefano Zampini 
660128143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6602854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
660328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
660428143c3dSStefano Zampini     psum = 0;
660528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
660628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
660728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
660828143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
660928143c3dSStefano Zampini         psum += plen;
661028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
661128143c3dSStefano Zampini       }
661228143c3dSStefano Zampini     }
6613854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6614854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
661528143c3dSStefano Zampini     for (i=1;i<nis;i++) {
661628143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
661728143c3dSStefano Zampini     }
661828143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
661928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
662028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
662128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
662228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
662328143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
662428143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
662528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
662628143c3dSStefano Zampini       }
662728143c3dSStefano Zampini     }
662828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
662928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
663028143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
663128143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
663228143c3dSStefano Zampini     }
663328143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
663428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
663528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
663628143c3dSStefano Zampini   }
6637e7931f94SStefano Zampini   /* free workspace */
663828143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6639e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6640e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6641e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6642e7931f94SStefano Zampini   if (isdense) {
6643e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6644e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6645e7931f94SStefano Zampini   } else {
6646e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6647e7931f94SStefano Zampini   }
664828143c3dSStefano Zampini   if (nis) {
664928143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
665028143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
665128143c3dSStefano Zampini   }
66521ae86dd6SStefano Zampini 
66531ae86dd6SStefano Zampini   if (nvecs) {
66541ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66551ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
66561ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
66571ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
66581ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
66591ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
66601ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
66611ae86dd6SStefano Zampini     /* set values */
66621ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
66631ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
66641ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
66651ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
66661ae86dd6SStefano Zampini       PetscInt j;
66671ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
66681ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
66691ae86dd6SStefano Zampini       }
66701ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
66711ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
66721ae86dd6SStefano Zampini     }
66731ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
66741ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
66751ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
66761ae86dd6SStefano Zampini   }
66771ae86dd6SStefano Zampini 
66781ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
66791ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6680e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6681e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
66821ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
668328143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6684e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6685e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
66861ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
668728143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6688e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6689e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6690e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6691e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6692e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
669328143c3dSStefano Zampini   if (nis) {
669428143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
669528143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
669628143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
669728143c3dSStefano Zampini   }
669828143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
669928143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
670028143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
670128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
670228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
670328143c3dSStefano Zampini     }
67041ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
67051ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
67061ae86dd6SStefano Zampini     }
670753a05cb3SStefano Zampini     *mat_n = NULL;
670828143c3dSStefano Zampini   }
6709e7931f94SStefano Zampini   PetscFunctionReturn(0);
6710e7931f94SStefano Zampini }
6711a57a6d2fSStefano Zampini 
671212edc857SStefano Zampini /* temporary hack into ksp private data structure */
6713af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
671412edc857SStefano Zampini 
6715c8587f34SStefano Zampini #undef __FUNCT__
6716c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6717c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6718c8587f34SStefano Zampini {
6719c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6720c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
672120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
67221ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
67239881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
672420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
67256e683305SStefano Zampini   IS                     coarse_is,*isarray;
67266e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
672730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6728f9eb5b7dSStefano Zampini   PC                     pc_temp;
6729c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6730c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6731f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
67324f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
67336e683305SStefano Zampini   Mat                    t_coarse_mat_is;
673457de7509SStefano Zampini   PetscInt               ncoarse;
673568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
673622bc73bbSStefano Zampini   PetscScalar            *array;
673757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
673857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
67399881197aSStefano Zampini   PetscErrorCode         ierr;
6740fdc09c96SStefano Zampini 
6741c8587f34SStefano Zampini   PetscFunctionBegin;
6742c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
674368457ee5SStefano 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 */
6744fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
67455a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6746fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6747f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6748f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6749f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6750fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
675151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
675251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6753dc4bcba2SStefano Zampini         PC        pc;
6754dc4bcba2SStefano Zampini         PetscBool isbddc;
6755dc4bcba2SStefano Zampini 
6756dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6757dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6758dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6759dc4bcba2SStefano Zampini         if (isbddc) {
676063c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
676163c961adSStefano Zampini         } else {
6762727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
676363c961adSStefano Zampini         }
6764fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6765fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6766fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6767f4ddd8eeSStefano Zampini       }
6768fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6769fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6770f4ddd8eeSStefano Zampini     }
677170cf5478SStefano Zampini     /* reset any subassembling information */
677257de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
677370cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
677457de7509SStefano Zampini     }
67756e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6776fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6777f4ddd8eeSStefano Zampini   }
677857de7509SStefano Zampini   /* assemble coarse matrix */
677957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
678057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
678157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
678257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
678318a45a71SStefano Zampini   } else {
678457de7509SStefano Zampini     coarse_mat = NULL;
678557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
67866e683305SStefano Zampini   }
6787e7931f94SStefano Zampini 
6788abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6789abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6790abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6791abbbba34SStefano Zampini 
6792abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
679322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
679422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
679522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
679622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6797e176bc59SStefano 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);
67986e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
67996e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68006e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6801abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6802abbbba34SStefano Zampini 
680357de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
680457de7509SStefano Zampini   im_active = !!(pcis->n);
680557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
680657de7509SStefano Zampini 
680714f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
680857de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
680957de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
681057de7509SStefano Zampini   coarse_mat_is = NULL;
681157de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
681257de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
681357de7509SStefano Zampini   full_restr = PETSC_TRUE;
68141ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
681557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
681657de7509SStefano Zampini   if (multilevel_requested) {
681757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
681857de7509SStefano Zampini     restr = PETSC_FALSE;
681957de7509SStefano Zampini     full_restr = PETSC_FALSE;
682057de7509SStefano Zampini   } else {
682157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
682257de7509SStefano Zampini     restr = PETSC_TRUE;
682357de7509SStefano Zampini     full_restr = PETSC_TRUE;
682457de7509SStefano Zampini   }
68254b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
682657de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
682757de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6828a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
682957de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6830a198735bSStefano Zampini     } else {
6831a198735bSStefano Zampini       PetscMPIInt size,rank;
6832a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6833a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6834a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6835a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6836a198735bSStefano Zampini     }
683757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
683857de7509SStefano Zampini     PetscInt    psum;
683957de7509SStefano Zampini     PetscMPIInt size;
684057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
684157de7509SStefano Zampini     else psum = 0;
684257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
684357de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
684457de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
684557de7509SStefano Zampini   }
684657de7509SStefano Zampini   /* determine if we can go multilevel */
684757de7509SStefano Zampini   if (multilevel_requested) {
684857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
684957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
685057de7509SStefano Zampini   }
685157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
685257de7509SStefano Zampini 
6853e4d548c7SStefano Zampini   /* dump subassembling pattern */
6854e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6855e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6856e4d548c7SStefano Zampini   }
6857e4d548c7SStefano Zampini 
68586e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
685927b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
68606e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
68616e683305SStefano Zampini     const PetscInt         *idxs;
68626e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
68636e683305SStefano Zampini 
68646e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
68650be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
68666e683305SStefano Zampini     /* allocate space for temporary storage */
6867854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6868854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
68696e683305SStefano Zampini     /* allocate for IS array */
68706e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
68716e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
687227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
687330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6874854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
68756e683305SStefano Zampini     /* dofs splitting */
68766e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
68776e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
68786e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
68796e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
68806e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
68816e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
68826e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
688330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
68846e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
68856e683305SStefano Zampini     }
68866e683305SStefano Zampini     /* neumann boundaries */
68876e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
68886e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
68896e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
68906e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
68916e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
68926e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
68936e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
689430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
68956e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
68966e683305SStefano Zampini     }
68976e683305SStefano Zampini     /* free memory */
68986e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
68996e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
69006e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
69016e683305SStefano Zampini   } else {
69026e683305SStefano Zampini     nis = 0;
69036e683305SStefano Zampini     nisdofs = 0;
69046e683305SStefano Zampini     nisneu = 0;
690530368db7SStefano Zampini     nisvert = 0;
69066e683305SStefano Zampini     isarray = NULL;
69076e683305SStefano Zampini   }
69086e683305SStefano Zampini   /* destroy no longer needed map */
69096e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
69106e683305SStefano Zampini 
691157de7509SStefano Zampini   /* subassemble */
691257de7509SStefano Zampini   if (multilevel_allowed) {
69131ae86dd6SStefano Zampini     Vec       vp[1];
69141ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
691557de7509SStefano Zampini     PetscBool reuse,reuser;
69161ae86dd6SStefano Zampini 
691757de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
691857de7509SStefano Zampini     else reuse = PETSC_FALSE;
691957de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
69201ae86dd6SStefano Zampini     vp[0] = NULL;
69211ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
69221ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
69231ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
69241ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
69251ae86dd6SStefano Zampini       nvecs = 1;
69261ae86dd6SStefano Zampini 
69271ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6928a198735bSStefano Zampini         Mat      B,loc_divudotp;
69291ae86dd6SStefano Zampini         Vec      v,p;
69301ae86dd6SStefano Zampini         IS       dummy;
69311ae86dd6SStefano Zampini         PetscInt np;
69321ae86dd6SStefano Zampini 
6933a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6934a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
69351ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6936a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
69371ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
69381ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
69391ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
69401ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
69411ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
69421ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
69431ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
69441ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
69451ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
69461ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
69471ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
69481ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
694974e2c79eSStefano Zampini       }
69501ae86dd6SStefano Zampini     }
69511ae86dd6SStefano Zampini     if (reuser) {
69521ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
695374e2c79eSStefano Zampini     } else {
69541ae86dd6SStefano 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);
69551ae86dd6SStefano Zampini     }
69561ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
69571ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
69581ae86dd6SStefano Zampini       PetscInt    nl;
69591ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
69601ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
69611ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
69621ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
69631ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
69641ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
69651ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
69661ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
6967a198735bSStefano Zampini     } else {
6968a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
69691ae86dd6SStefano Zampini     }
69701ae86dd6SStefano Zampini   } else {
69711ae86dd6SStefano 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);
69726e683305SStefano Zampini   }
697357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
697457de7509SStefano Zampini     PetscMPIInt size;
697557de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
697657de7509SStefano Zampini     if (!multilevel_allowed) {
697757de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
69786e683305SStefano Zampini     } else {
697957de7509SStefano Zampini       Mat A;
6980779c1cceSStefano Zampini 
698157de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
698257de7509SStefano Zampini       if (coarse_mat_is) {
698357de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
698457de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
698557de7509SStefano Zampini         coarse_mat = coarse_mat_is;
698657de7509SStefano Zampini       }
698757de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
698857de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
698957de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
6990779c1cceSStefano Zampini     }
6991779c1cceSStefano Zampini   }
699257de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
699357de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
69946e683305SStefano Zampini 
69956e683305SStefano Zampini   /* create local to global scatters for coarse problem */
699668457ee5SStefano Zampini   if (compute_vecs) {
69976e683305SStefano Zampini     PetscInt lrows;
69986e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
699957de7509SStefano Zampini     if (coarse_mat) {
700057de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
70016e683305SStefano Zampini     } else {
70026e683305SStefano Zampini       lrows = 0;
70036e683305SStefano Zampini     }
70046e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
70056e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
70066e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
70076e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70086e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
70096e683305SStefano Zampini   }
70106e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
7011c8587f34SStefano Zampini 
7012f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
7013f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
7014f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
7015f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
7016f9eb5b7dSStefano Zampini   } else {
7017f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
7018f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
7019c8587f34SStefano Zampini   }
7020c8587f34SStefano Zampini 
70216e683305SStefano Zampini   /* print some info if requested */
70226e683305SStefano Zampini   if (pcbddc->dbg_flag) {
70236e683305SStefano Zampini     if (!multilevel_allowed) {
70246e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
70256e683305SStefano Zampini       if (multilevel_requested) {
70266e683305SStefano 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);
70276e683305SStefano Zampini       } else if (pcbddc->max_levels) {
70286e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
70296e683305SStefano Zampini       }
70306e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
70316e683305SStefano Zampini     }
70326e683305SStefano Zampini   }
70336e683305SStefano Zampini 
7034f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
703557de7509SStefano Zampini   if (coarse_mat) {
70366a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
70376e683305SStefano Zampini     if (pcbddc->dbg_flag) {
703857de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
70396e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
70406e683305SStefano Zampini     }
7041f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
7042312be037SStefano Zampini       char prefix[256],str_level[16];
7043e604994aSStefano Zampini       size_t len;
704457de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
7045422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
7046c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7047f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
704857de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7049c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
70506e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
7051c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
7052c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7053e604994aSStefano Zampini       /* prefix */
7054e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
7055e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
7056e604994aSStefano Zampini       if (!pcbddc->current_level) {
7057e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
7058e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
7059c8587f34SStefano Zampini       } else {
7060e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
7061312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
7062312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
706334d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
7064312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
7065e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
7066e604994aSStefano Zampini       }
7067e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
70683e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
70693e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
70703e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
70713e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
7072f9eb5b7dSStefano Zampini       /* allow user customization */
7073f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
70743e3c6dadSStefano Zampini     }
70753e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
707651bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
70773e3c6dadSStefano Zampini     if (nisdofs) {
70783e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
70793e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
70803e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
70813e3c6dadSStefano Zampini       }
70823e3c6dadSStefano Zampini     }
70833e3c6dadSStefano Zampini     if (nisneu) {
70843e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
70853e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
7086312be037SStefano Zampini     }
708730368db7SStefano Zampini     if (nisvert) {
708830368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
708930368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
709030368db7SStefano Zampini     }
7091f9eb5b7dSStefano Zampini 
7092f9eb5b7dSStefano Zampini     /* get some info after set from options */
7093f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
7094f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
70954f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
70966e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
7097f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
7098f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
7099f9eb5b7dSStefano Zampini     }
710039f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
71014f3a063dSStefano Zampini     if (isredundant) {
71024f3a063dSStefano Zampini       KSP inner_ksp;
71034f3a063dSStefano Zampini       PC  inner_pc;
71044f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
71054f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
71064f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
71074f3a063dSStefano Zampini     }
7108f9eb5b7dSStefano Zampini 
710957de7509SStefano Zampini     /* parameters which miss an API */
711057de7509SStefano Zampini     if (isbddc) {
7111720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
7112720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
711357de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
711427b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
711527b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
7116a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
7117a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
7118a198735bSStefano Zampini         IS                     row,col;
7119a198735bSStefano Zampini         const PetscInt         *gidxs;
7120a198735bSStefano Zampini         PetscInt               n,st,M,N;
7121a198735bSStefano Zampini 
7122a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
7123a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
7124a198735bSStefano Zampini         st = st-n;
7125a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
7126a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
7127a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
7128a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7129a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
7130a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
7131a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
7132a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
7133a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
7134a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
7135a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
7136a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
7137a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
7138a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
7139a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
7140a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
7141a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7142a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7143a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
7144a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
71458ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
7146a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
7147720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
714859e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
7149720d30f9SStefano Zampini       }
7150d4d8cf7bSStefano Zampini     }
71519881197aSStefano Zampini 
71523301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
71535a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
71543301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
71553301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
71563301b35fSStefano Zampini     }
71573301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
71583301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
71593301b35fSStefano Zampini     }
71603301b35fSStefano Zampini     if (pc->pmat->spd_set) {
71613301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
71623301b35fSStefano Zampini     }
716327b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
716427b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
716527b6a85dSStefano Zampini     }
71666e683305SStefano Zampini     /* set operators */
71675f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
71686e683305SStefano Zampini     if (pcbddc->dbg_flag) {
71696e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
71706e683305SStefano Zampini     }
71716e683305SStefano Zampini   }
71726e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
7173b1ecc7b1SStefano Zampini #if 0
7174b9b85e73SStefano Zampini   {
7175b9b85e73SStefano Zampini     PetscViewer viewer;
7176b9b85e73SStefano Zampini     char filename[256];
7177b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7178b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
71796a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7180b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7181f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7182b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7183b9b85e73SStefano Zampini   }
7184b9b85e73SStefano Zampini #endif
7185f9eb5b7dSStefano Zampini 
718698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
718798a51de6SStefano Zampini     Vec crhs,csol;
718804708bb6SStefano Zampini 
7189f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7190f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7191f347579bSStefano Zampini     if (!csol) {
71922a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7193f9eb5b7dSStefano Zampini     }
7194f347579bSStefano Zampini     if (!crhs) {
71952a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7196f347579bSStefano Zampini     }
7197b0f5fe93SStefano Zampini   }
71981ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7199b0f5fe93SStefano Zampini 
7200b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7201b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7202b0f5fe93SStefano Zampini 
7203b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
72044f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
72054f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
72064f1b2e48SStefano Zampini     }
7207b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7208b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7209b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7210b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7211b0f5fe93SStefano Zampini     if (coarse_mat) {
7212b0f5fe93SStefano Zampini       Vec         nullv;
7213b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7214b0f5fe93SStefano Zampini       PetscInt    nl;
7215b0f5fe93SStefano Zampini 
7216b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7217b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7218b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7219b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7220b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7221b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7222b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7223b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7224b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7225b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7226b0f5fe93SStefano Zampini     }
7227b0f5fe93SStefano Zampini   }
7228b0f5fe93SStefano Zampini 
7229b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7230b0f5fe93SStefano Zampini     PetscBool ispreonly;
7231b0f5fe93SStefano Zampini 
7232b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7233b0f5fe93SStefano Zampini       PetscBool isnull;
7234b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7235bef83e63SStefano Zampini       if (isnull) {
7236b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7237b0f5fe93SStefano Zampini       }
7238bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7239b0f5fe93SStefano Zampini     }
7240b0f5fe93SStefano Zampini     /* setup coarse ksp */
7241b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7242cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7243cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
72446e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7245c8587f34SStefano Zampini       KSP       check_ksp;
72462b510759SStefano Zampini       KSPType   check_ksp_type;
7247c8587f34SStefano Zampini       PC        check_pc;
72486e683305SStefano Zampini       Vec       check_vec,coarse_vec;
72496a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
72502b510759SStefano Zampini       PetscInt  its;
72516e683305SStefano Zampini       PetscBool compute_eigs;
72526e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
72536e683305SStefano Zampini       PetscInt  neigs;
72548e185a42SStefano Zampini       const char *prefix;
7255c8587f34SStefano Zampini 
72562b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
72576e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7258422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
725923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7260f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7261e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7262e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7263e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
72642b510759SStefano Zampini       if (ispreonly) {
72652b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
72666e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
72672b510759SStefano Zampini       } else {
7268cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
72696e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7270c8587f34SStefano Zampini       }
7271c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
72726e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
72736e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
72746e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7275a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7276a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7277a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7278a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7279c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7280c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7281c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7282c8587f34SStefano Zampini       /* create random vec */
72832701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7284c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
72856e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7286c8587f34SStefano Zampini       /* solve coarse problem */
72876e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7288cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
72896e683305SStefano Zampini       if (compute_eigs) {
7290854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7291854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
72926e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
72931ae86dd6SStefano Zampini         if (neigs) {
72946e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
72956e683305SStefano Zampini           lambda_min = eigs_r[0];
72966e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
72972701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
72982701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7299cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7300cbcc2c2aSStefano Zampini             }
7301c8587f34SStefano Zampini           }
7302c8587f34SStefano Zampini         }
73031ae86dd6SStefano Zampini       }
7304cbcc2c2aSStefano Zampini 
7305c8587f34SStefano Zampini       /* check coarse problem residual error */
73066e683305SStefano Zampini       if (pcbddc->dbg_flag) {
73076e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
73086e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73096e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7310c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
73116e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
73126e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7313779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
73146e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
73156e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
73166e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
73176e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7318b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7319b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7320b0f5fe93SStefano Zampini         }
73216e683305SStefano Zampini         if (compute_eigs) {
73226e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7323deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7324c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
73256e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
73266e683305SStefano 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);
73276e683305SStefano Zampini           for (i=0;i<neigs;i++) {
73286e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7329c8587f34SStefano Zampini           }
73306e683305SStefano Zampini         }
73316e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
73326e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
73336e683305SStefano Zampini       }
7334e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
73352701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7336c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
73376e683305SStefano Zampini       if (compute_eigs) {
73386e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
73396e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7340c8587f34SStefano Zampini       }
73416e683305SStefano Zampini     }
73426e683305SStefano Zampini   }
7343bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7344cbcc2c2aSStefano Zampini   /* print additional info */
7345cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
73466e683305SStefano Zampini     /* waits until all processes reaches this point */
73476e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7348cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7349cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7350cbcc2c2aSStefano Zampini   }
7351cbcc2c2aSStefano Zampini 
73522b510759SStefano Zampini   /* free memory */
7353fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7354c8587f34SStefano Zampini   PetscFunctionReturn(0);
7355c8587f34SStefano Zampini }
7356674ae819SStefano Zampini 
7357f34684f1SStefano Zampini #undef __FUNCT__
7358f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7359f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7360f34684f1SStefano Zampini {
7361f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7362f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7363f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7364dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7365dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
736673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7367dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7368f34684f1SStefano Zampini   PetscErrorCode ierr;
7369f34684f1SStefano Zampini 
7370f34684f1SStefano Zampini   PetscFunctionBegin;
7371f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
73726c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7373dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
73743bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7375dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7376dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
73776583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7378dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7379dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7380dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
73816c4ed002SBarry 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);
7382dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7383dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7384dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7385dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7386dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7387f34684f1SStefano Zampini 
7388f34684f1SStefano Zampini   /* check numbering */
7389f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7390019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7391dc456d91SStefano Zampini     PetscInt    i;
7392b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7393f34684f1SStefano Zampini 
7394f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7395f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7396f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
73971575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7398019a44ceSStefano Zampini     /* counter */
7399019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7400019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7401019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7402019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7403019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7404019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7405f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7406f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7407727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7408f34684f1SStefano Zampini     }
7409f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7410f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7411f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7412e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7413e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7414e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7415e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7416f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7417019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7418f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7419019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
74202c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
742175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7422b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
74232c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
74242c66d082SStefano 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);
7425f34684f1SStefano Zampini       }
7426f34684f1SStefano Zampini     }
7427019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7428b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7429f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7430f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7431f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7432f34684f1SStefano Zampini     }
7433f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7434f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7435e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7436e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7437f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7438f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7439b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7440ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7441ca8b9ea9SStefano Zampini 
7442ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
74433bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7444f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7445f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7446f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7447f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
74484bc2dc4bSStefano 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);
7449f34684f1SStefano Zampini       }
7450f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7451ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7452f34684f1SStefano Zampini     }
7453f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74541575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7455302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7456f34684f1SStefano Zampini   }
74578bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7458f34684f1SStefano Zampini   /* get back data */
7459f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7460f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7461674ae819SStefano Zampini   PetscFunctionReturn(0);
7462674ae819SStefano Zampini }
7463674ae819SStefano Zampini 
7464e456f2a8SStefano Zampini #undef __FUNCT__
7465e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7466a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7467e456f2a8SStefano Zampini {
7468e456f2a8SStefano Zampini   IS             localis_t;
7469a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7470e456f2a8SStefano Zampini   PetscScalar    *vals;
7471e456f2a8SStefano Zampini   PetscErrorCode ierr;
7472e456f2a8SStefano Zampini 
7473e456f2a8SStefano Zampini   PetscFunctionBegin;
7474a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7475e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7476854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7477e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7478e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7479a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7480a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
74811035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7482a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
74831035eff8SStefano Zampini   }
7484a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7485e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7486e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7487a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7488a7dc3881SStefano Zampini   /* now compute set in local ordering */
7489a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7490a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7491a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7492a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7493a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7494ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7495e456f2a8SStefano Zampini       lsize++;
7496e456f2a8SStefano Zampini     }
7497e456f2a8SStefano Zampini   }
7498854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7499a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7500ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7501e456f2a8SStefano Zampini       idxs[lsize++] = i;
7502e456f2a8SStefano Zampini     }
7503e456f2a8SStefano Zampini   }
7504a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7505a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7506e456f2a8SStefano Zampini   *localis = localis_t;
7507e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7508e456f2a8SStefano Zampini }
7509906d46d4SStefano Zampini 
7510b96c3477SStefano Zampini #undef __FUNCT__
7511b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
751208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7513b96c3477SStefano Zampini {
7514a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7515b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7516b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7517a64f4aa4SStefano Zampini   Mat                 S_j;
7518b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7519b96c3477SStefano Zampini   PetscBool           free_used_adj;
7520b96c3477SStefano Zampini   PetscErrorCode      ierr;
7521b96c3477SStefano Zampini 
7522b96c3477SStefano Zampini   PetscFunctionBegin;
7523b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7524b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
752508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7526b96c3477SStefano Zampini     used_xadj = NULL;
7527b96c3477SStefano Zampini     used_adjncy = NULL;
7528b96c3477SStefano Zampini   } else {
752908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
753008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
753108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
753208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7533b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7534b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7535b96c3477SStefano Zampini     } else {
75362fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7537b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7538b96c3477SStefano Zampini       PetscInt       nvtxs;
7539b96c3477SStefano Zampini 
75402fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
75412fffb893SStefano Zampini       if (flg_row) {
7542b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7543b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7544b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7545b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
75462fffb893SStefano Zampini       } else {
75472fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
75482fffb893SStefano Zampini         used_xadj = NULL;
75492fffb893SStefano Zampini         used_adjncy = NULL;
75502fffb893SStefano Zampini       }
75512fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7552b96c3477SStefano Zampini     }
7553b96c3477SStefano Zampini   }
7554d5574798SStefano Zampini 
7555d5574798SStefano Zampini   /* setup sub_schurs data */
7556a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7557df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7558df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7559a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
756091af6908SStefano 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);
7561a64f4aa4SStefano Zampini   } else {
75626816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
75634d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7564a3df083aSStefano Zampini     PetscInt  benign_n;
756572b8c272SStefano Zampini     Mat       change = NULL;
75669d54b7f4SStefano Zampini     Vec       scaling = NULL;
756772b8c272SStefano Zampini     IS        change_primal = NULL;
7568a3df083aSStefano Zampini 
75695feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
75705feab87aSStefano Zampini       PetscInt n_vertices;
75715feab87aSStefano Zampini 
75725feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
75732034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
75745feab87aSStefano Zampini     }
757504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
757604708bb6SStefano Zampini     if (!isseqaij) {
757704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
757804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
757904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
758004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
758104708bb6SStefano Zampini       } else {
7582511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
758304708bb6SStefano Zampini       }
758404708bb6SStefano Zampini     }
7585a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7586a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7587ca92afb2SStefano Zampini     } else {
7588a3df083aSStefano Zampini       benign_n = 0;
7589ca92afb2SStefano Zampini     }
7590b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7591b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7592b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
759372b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
759422db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7595b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
759622db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7597b7ab4a40SStefano Zampini     }
7598b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7599b7ab4a40SStefano 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 */
7600b7ab4a40SStefano Zampini     if (need_change) {
760188c03ad3SStefano Zampini       PC_IS   *pcisf;
760288c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
760388c03ad3SStefano Zampini       PC      pcf;
760488c03ad3SStefano Zampini 
7605e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
760688c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
760788c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
760888c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
760988c03ad3SStefano Zampini       /* hacks */
761088c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
761172b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
761272b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
761372b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
761472b8c272SStefano Zampini       pcisf->n = pcis->n;
761572b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
761688c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
761788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
761888c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
761988c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
762088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
762188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
762272b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
762388c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
762488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
762572b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
762672b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
762772b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
762872b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
762972b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
763088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
763172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
763288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
763388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
763488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
763588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
763688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
763788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
763888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
763988c03ad3SStefano Zampini     }
76409d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
764191af6908SStefano 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);
764272b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
764372b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7644ca92afb2SStefano Zampini   }
7645d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7646b96c3477SStefano Zampini 
7647b96c3477SStefano Zampini   /* free adjacency */
7648b96c3477SStefano Zampini   if (free_used_adj) {
7649b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7650b96c3477SStefano Zampini   }
7651b96c3477SStefano Zampini   PetscFunctionReturn(0);
7652b96c3477SStefano Zampini }
7653b96c3477SStefano Zampini 
7654b96c3477SStefano Zampini #undef __FUNCT__
7655b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
765608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7657b96c3477SStefano Zampini {
7658b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7659b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7660b96c3477SStefano Zampini   PCBDDCGraph         graph;
7661b96c3477SStefano Zampini   PetscErrorCode      ierr;
7662b96c3477SStefano Zampini 
7663b96c3477SStefano Zampini   PetscFunctionBegin;
7664b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
766508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
76663301b35fSStefano Zampini     IS       verticesIS,verticescomm;
76673301b35fSStefano Zampini     PetscInt vsize,*idxs;
7668b96c3477SStefano Zampini 
7669b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
76703301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
76713301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
76723301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
76733301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7674c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7675b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7676be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7677441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
76783301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7679b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7680b96c3477SStefano Zampini   } else {
7681b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7682b96c3477SStefano Zampini   }
7683e4d548c7SStefano Zampini   /* print some info */
7684e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7685e4d548c7SStefano Zampini     IS       vertices;
7686e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7687c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7688e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7689e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7690e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7691e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7692e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7693e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7694e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7695e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7696e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7697c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7698e4d548c7SStefano Zampini   }
7699b96c3477SStefano Zampini 
7700b96c3477SStefano Zampini   /* sub_schurs init */
7701b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7702b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7703b334f244SStefano Zampini   }
7704b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7705a64f4aa4SStefano Zampini 
7706b96c3477SStefano Zampini   /* free graph struct */
770708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7708b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7709b96c3477SStefano Zampini   }
7710b96c3477SStefano Zampini   PetscFunctionReturn(0);
7711b96c3477SStefano Zampini }
7712fa34dd3eSStefano Zampini 
7713fa34dd3eSStefano Zampini #undef __FUNCT__
7714fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7715fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7716fa34dd3eSStefano Zampini {
7717fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7718fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7719fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7720fa34dd3eSStefano Zampini 
7721fa34dd3eSStefano Zampini   PetscFunctionBegin;
7722fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7723fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
77244f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7725fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
77264f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
772775c01103SStefano Zampini     PetscReal      norm;
7728fa34dd3eSStefano Zampini     PetscInt       i;
7729fa34dd3eSStefano Zampini 
7730fa34dd3eSStefano Zampini     /* B0 and B0_B */
7731fa34dd3eSStefano Zampini     if (zerodiag) {
7732fa34dd3eSStefano Zampini       IS       dummy;
7733fa34dd3eSStefano Zampini 
77344f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
77354f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7736fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7737fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7738fa34dd3eSStefano Zampini     }
7739fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7740fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7741fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7742fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7743fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7744fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7745fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7746fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7747fa34dd3eSStefano Zampini     /* S_j */
7748fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7749fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7750fa34dd3eSStefano Zampini 
7751fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7752fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7753fa34dd3eSStefano Zampini     /* continuous in primal space */
7754fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7755fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7756fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7757fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
77584f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
77594f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7760fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7761fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7762fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7763fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7764fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7765fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7766fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7767fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7768fa34dd3eSStefano Zampini 
7769fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7770fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7771fa34dd3eSStefano Zampini     /* local with Schur */
7772fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7773fa34dd3eSStefano Zampini     if (zerodiag) {
7774fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
77754f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7776fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7777fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7778fa34dd3eSStefano Zampini     }
7779fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7780fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7781fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7782fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7783fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7784fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7785fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7786fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7787fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7788fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7789fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7790fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7791fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7792fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7793fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7794fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7795fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7796fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7797fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7798fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7799fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7800fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7801fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7802fa34dd3eSStefano Zampini     if (zerodiag) {
7803fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7804fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
78054f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7806fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7807fa34dd3eSStefano Zampini     }
7808fa34dd3eSStefano Zampini     /* BDDC */
7809fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7810fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7811fa34dd3eSStefano Zampini 
7812fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7813fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7814fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7815fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
78164f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
78174f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7818fa34dd3eSStefano Zampini     }
78194f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7820fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7821fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7822fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7823fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7824fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7825fa34dd3eSStefano Zampini   }
7826fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7827fa34dd3eSStefano Zampini }
7828