xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision be12c13469a3bc9ab17b9f62f1726d40dec0aeb3)
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);
83a13144ffSStefano Zampini   ierr = ISGetSize(extrow,&rsize);CHKERRQ(ierr);
84a13144ffSStefano Zampini   ierr = ISGetSize(extcol,&csize);CHKERRQ(ierr);
85a13144ffSStefano Zampini 
86a13144ffSStefano Zampini   /* gradients */
87a13144ffSStefano Zampini   ptr  = work + 5*esize;
88a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
89a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins);CHKERRQ(ierr);
90a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins);CHKERRQ(ierr);
91a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
92a13144ffSStefano Zampini 
93a13144ffSStefano Zampini   /* constants */
94a13144ffSStefano Zampini   ptr += rsize*csize;
95a13144ffSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd);CHKERRQ(ierr);
96a13144ffSStefano Zampini   ierr = MatGetSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE);CHKERRQ(ierr);
97a13144ffSStefano Zampini   ierr = MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd);CHKERRQ(ierr);
98a13144ffSStefano Zampini   ierr = MatDestroy(&GE);CHKERRQ(ierr);
99a13144ffSStefano Zampini   ierr = MatDense_OrthogonalComplement(GEd,5*esize,work,rwork,GKins);CHKERRQ(ierr);
100a13144ffSStefano Zampini   ierr = MatDestroy(&GEd);CHKERRQ(ierr);
101a13144ffSStefano Zampini   PetscFunctionReturn(0);
102a13144ffSStefano Zampini }
103a13144ffSStefano Zampini 
104a13144ffSStefano Zampini #undef __FUNCT__
105a13144ffSStefano Zampini #define __FUNCT__ "PCBDDCNedelecSupport"
106a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc)
107a13144ffSStefano Zampini {
108a13144ffSStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
109a13144ffSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)pc->pmat->data;
110a13144ffSStefano Zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGw;
111a13144ffSStefano Zampini   MatNullSpace           nnsp;
112a13144ffSStefano Zampini   Vec                    tvec,*quads;
113a13144ffSStefano Zampini   PetscSF                sfv;
114a13144ffSStefano Zampini   ISLocalToGlobalMapping el2g,vl2g;
115a13144ffSStefano Zampini   MPI_Comm               comm;
116a13144ffSStefano Zampini   IS                     lned,primals;
117a13144ffSStefano Zampini   IS                     *eedges,*extrows,*extcols;
118a13144ffSStefano Zampini   PetscBT                btv,bte,btb,btvcand,iwork;
119a13144ffSStefano Zampini   PetscScalar            *vals,*work;
120a13144ffSStefano Zampini   PetscReal              *rwork;
121a13144ffSStefano Zampini   const PetscInt         *idxs,*ii,*jj,*iit,*jjt;
122a13144ffSStefano Zampini   PetscInt               ne,nv,Ne,Nv,Le,Lv,order;
123a13144ffSStefano Zampini   PetscInt               n_neigh,*neigh,*n_shared,**shared;
124a13144ffSStefano Zampini   PetscInt               *interior;
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;
128a13144ffSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,ismpiaij;
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);
140a13144ffSStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(el2g,&ne);CHKERRQ(ierr);
141a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
142a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
143a13144ffSStefano Zampini   for (i=0;i<ne;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 
153a13144ffSStefano Zampini   /* Get relevant objects */
154a13144ffSStefano Zampini   G          = pcbddc->discretegradient;
155a13144ffSStefano Zampini   order      = pcbddc->nedorder;
156a13144ffSStefano Zampini   conforming = pcbddc->conforming;
157a13144ffSStefano Zampini 
158a13144ffSStefano Zampini   /* Compute local and global sizes of egde dofs and nodal dofs */
159a13144ffSStefano Zampini   ierr = MatGetSize(G,&Ne,&Nv);CHKERRQ(ierr);
160a13144ffSStefano Zampini   ierr = MatGetLocalSize(G,&Le,&Lv);CHKERRQ(ierr);
161a13144ffSStefano Zampini 
162a13144ffSStefano Zampini   /* Sanity checks */
163a13144ffSStefano Zampini   if (!order) SETERRQ(comm,PETSC_ERR_SUP,"Variable order not yet implemented");
164a13144ffSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
165a13144ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)G,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
166a13144ffSStefano Zampini   if (!ismpiaij) SETERRQ1(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with discrete gradient of type %s. Please use MPIAIJ",((PetscObject)G)->type_name);
167a13144ffSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
168a13144ffSStefano Zampini   if (order && Ne%order) SETERRQ2(comm,PETSC_ERR_USER,"The number of edge dofs %d it's not a multiple of the order %d",Ne,order);
169a13144ffSStefano 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);
170a13144ffSStefano Zampini   ierr = MatGetSize(pc->pmat,&i,NULL);CHKERRQ(ierr);
171a13144ffSStefano Zampini   if (Ne != i) SETERRQ2(comm,PETSC_ERR_USER,"Global matrix sizes should match! Number of rows of G %d differs from that of A %d",Ne,i);
172a13144ffSStefano Zampini   ierr = MatGetLocalSize(pc->pmat,&i,NULL);CHKERRQ(ierr);
173a13144ffSStefano Zampini   if (Le != i) SETERRQ2(comm,PETSC_ERR_USER,"Local matrix sizes should match! Number of local rows of G %d differs from that of A %d",Le,i);
174a13144ffSStefano Zampini 
175a13144ffSStefano Zampini   /* Drop connections for interior edges (this modifies G) */
176a13144ffSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
177a13144ffSStefano Zampini   ierr = VecScatterBegin(matis->rctx,matis->counter,tvec,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
178a13144ffSStefano Zampini   ierr = VecScatterEnd(matis->rctx,matis->counter,tvec,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
179a13144ffSStefano Zampini   ierr = PetscMalloc1(Le,&marks);CHKERRQ(ierr);
180a13144ffSStefano Zampini   ierr = VecGetOwnershipRange(tvec,&rst,NULL);CHKERRQ(ierr);
181a13144ffSStefano Zampini   ierr = VecGetArrayRead(tvec,(const PetscScalar**)&vals);CHKERRQ(ierr);
182a13144ffSStefano Zampini   cum  = 0;
183a13144ffSStefano Zampini   for (i=0;i<Le;i++) if (PetscRealPart(vals[i]) < 1.5) marks[cum++] = i+rst;
184a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&vals);CHKERRQ(ierr);
185a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
186a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
187a13144ffSStefano Zampini   ierr = MatZeroRows(G,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
188a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
189a13144ffSStefano Zampini 
190a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
191a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
192a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
193a13144ffSStefano Zampini   ierr = MatGetSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
194a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
195a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
196a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
197a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
198a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
199a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
200a13144ffSStefano Zampini   if (print) {
201a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
202a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
203a13144ffSStefano Zampini   }
204a13144ffSStefano Zampini 
205a13144ffSStefano Zampini   /* SF for nodal communications */
206a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
207a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
208a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
209a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
210a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
211a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
212a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
213a13144ffSStefano Zampini   ierr = PetscMalloc2(nv,&sfvleaves,Lv,&sfvroots);CHKERRQ(ierr);
214a13144ffSStefano Zampini 
215a13144ffSStefano Zampini   /* Destroy temporary G created in MATIS format */
216a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
217a13144ffSStefano Zampini 
218a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
219a13144ffSStefano Zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGw);CHKERRQ(ierr);
220a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
221a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
222a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
223a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
224a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
225a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
226a13144ffSStefano Zampini     ierr = ISGetLocalSize(pcbddc->DirichletBoundariesLocal,&cum);CHKERRQ(ierr);
227a13144ffSStefano Zampini     ierr = ISGetIndices(pcbddc->DirichletBoundariesLocal,&idxs);CHKERRQ(ierr);
228a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
229a13144ffSStefano Zampini       if (idxs[i] >= 0) {
230a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
231a13144ffSStefano Zampini       }
232a13144ffSStefano Zampini     }
233a13144ffSStefano Zampini     ierr = ISRestoreIndices(pcbddc->DirichletBoundariesLocal,&idxs);CHKERRQ(ierr);
234a13144ffSStefano Zampini   }
235a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
236a13144ffSStefano Zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&cum);CHKERRQ(ierr);
237a13144ffSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
238a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
239a13144ffSStefano Zampini       if (idxs[i] >= 0) {
240a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
241a13144ffSStefano Zampini       }
242a13144ffSStefano Zampini     }
243a13144ffSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
244a13144ffSStefano Zampini   }
245a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
246a13144ffSStefano Zampini   /* need to remove coarse faces' dofs to ensure the
247a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
248a13144ffSStefano Zampini   ierr = PetscCalloc1(ne,&marks);CHKERRQ(ierr);
249a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
250a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
251a13144ffSStefano Zampini     PetscInt j;
252a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) marks[shared[i][j]]++;
253a13144ffSStefano Zampini   }
254a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
255a13144ffSStefano Zampini   cum  = 0;
256a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGw,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
257a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
258a13144ffSStefano Zampini     if (!marks[i] || (marks[i] == 1 && !PetscBTLookup(btb,i))) { /* eliminate rows corresponding to edge dofs belonging to coarse faces */
259a13144ffSStefano Zampini       marks[cum++] = i;
260a13144ffSStefano Zampini     } else if (!conforming && ii[i+1]-ii[i] != order + 1) { /* set badly connected edge dofs as primal */
261a13144ffSStefano Zampini       marks[cum++] = i;
262a13144ffSStefano Zampini       ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
263a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
264a13144ffSStefano Zampini         ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
265a13144ffSStefano Zampini       }
266a13144ffSStefano Zampini     }
267a13144ffSStefano Zampini   }
268a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGw,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
269a13144ffSStefano Zampini   ierr = MatSetOption(lGw,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
270a13144ffSStefano Zampini   ierr = MatZeroRows(lGw,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
271a13144ffSStefano Zampini   /* identify splitpoints and corner candidates: TODO variable order */
272a13144ffSStefano Zampini   ierr = MatTranspose(lGw,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
273a13144ffSStefano Zampini   if (print) {
274a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGw,"work_lG");CHKERRQ(ierr);
275a13144ffSStefano Zampini     ierr = MatView(lGw,NULL);CHKERRQ(ierr);
276a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"work_lGt");CHKERRQ(ierr);
277a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
278a13144ffSStefano Zampini   }
279a13144ffSStefano Zampini   ierr = MatDestroy(&lGw);CHKERRQ(ierr);
280a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
281a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
282a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
283a13144ffSStefano Zampini     if ((ii[i+1]-ii[i])%order) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",ii[i+1]-ii[i],i,order);
284a13144ffSStefano Zampini #endif
285a13144ffSStefano Zampini     if (ii[i+1]-ii[i] >= 3*order) { /* splitpoints */
286a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
287a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
288a13144ffSStefano Zampini     } else if (ii[i+1]-ii[i] == order) {
289a13144ffSStefano Zampini       if (order == 1) {
290a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
291a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
292a13144ffSStefano Zampini       } else {
293a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
294a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
295a13144ffSStefano Zampini       }
296a13144ffSStefano Zampini     }
297a13144ffSStefano Zampini   }
298a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
299a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
300a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
301a13144ffSStefano Zampini 
302a13144ffSStefano Zampini   /* Get the local G^T explicitly */
303a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
304a13144ffSStefano Zampini   if (print) {
305a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"initial_lGt");CHKERRQ(ierr);
306a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
307a13144ffSStefano Zampini   }
308a13144ffSStefano Zampini 
309a13144ffSStefano Zampini   /* Eliminate interior nodal dofs */
310a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
311a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&iwork);CHKERRQ(ierr);
312a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&interior);CHKERRQ(ierr);
313a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
314a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
315a13144ffSStefano Zampini       ierr = PetscBTSet(iwork,shared[i][j]);CHKERRQ(ierr);
316a13144ffSStefano Zampini     }
317a13144ffSStefano Zampini   }
318a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
319a13144ffSStefano Zampini   for (i=0,cum=0;i<nv;i++) if (!PetscBTLookup(iwork,i)) interior[cum++] = i;
320a13144ffSStefano Zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
321a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,interior,0.,NULL,NULL);CHKERRQ(ierr);
322a13144ffSStefano Zampini   if (print) {
323a13144ffSStefano Zampini     IS tbz;
324a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,interior,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
325a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"interior_nodal_dofs");CHKERRQ(ierr);
326a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
327a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
328a13144ffSStefano Zampini   }
329a13144ffSStefano Zampini   ierr = PetscBTDestroy(&iwork);CHKERRQ(ierr);
330a13144ffSStefano Zampini   ierr = PetscFree(interior);CHKERRQ(ierr);
331a13144ffSStefano Zampini 
332a13144ffSStefano Zampini   /* communicate corners and splitpoints */
333a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
334a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
335a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
336a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
337a13144ffSStefano Zampini 
338a13144ffSStefano Zampini   if (print) {
339a13144ffSStefano Zampini     IS tbz;
340a13144ffSStefano Zampini 
341a13144ffSStefano Zampini     cum = 0;
342a13144ffSStefano Zampini     for (i=0;i<nv;i++)
343a13144ffSStefano Zampini       if (sfvleaves[i])
344a13144ffSStefano Zampini         vmarks[cum++] = i;
345a13144ffSStefano Zampini 
346a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
347a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
348a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
349a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
350a13144ffSStefano Zampini   }
351a13144ffSStefano Zampini 
352a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
353a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
354a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
355a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
356a13144ffSStefano Zampini 
357a13144ffSStefano Zampini   /* Zero rows of lGt corresponding to identified corners (if any)
358a13144ffSStefano Zampini      TODO: this can be merged with the previous zerorows call */
359a13144ffSStefano Zampini   cum = 0;
360a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
361a13144ffSStefano Zampini     if (sfvleaves[i]) {
362a13144ffSStefano Zampini       vmarks[cum++] = i;
363a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
364a13144ffSStefano Zampini     }
365a13144ffSStefano Zampini   }
366a13144ffSStefano Zampini   if (print) {
367a13144ffSStefano Zampini     IS tbz;
368a13144ffSStefano Zampini 
369a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
370a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed");CHKERRQ(ierr);
371a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
372a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
373a13144ffSStefano Zampini   }
374a13144ffSStefano Zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
375a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
376a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
377a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
378a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
379a13144ffSStefano Zampini 
380a13144ffSStefano Zampini   /* Recompute G */
381a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
382a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
383a13144ffSStefano Zampini   if (print) {
384a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
385a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
386a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
387a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
388a13144ffSStefano Zampini   }
389a13144ffSStefano Zampini 
390a13144ffSStefano Zampini   /* Get primal dofs (if any) */
391a13144ffSStefano Zampini   cum = 0;
392a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
393a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
394a13144ffSStefano Zampini   }
395a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
396a13144ffSStefano Zampini   if (print) {
397a13144ffSStefano Zampini    ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
398a13144ffSStefano Zampini    ierr = ISView(primals,NULL);CHKERRQ(ierr);
399a13144ffSStefano Zampini   }
400a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
401a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
402a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
403a13144ffSStefano Zampini 
404a13144ffSStefano Zampini   /* Compute edge connectivity */
405a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
406a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
407a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
408a13144ffSStefano Zampini   ierr = PCBDDCSetLocalAdjacencyGraph(pc,ne,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
409a13144ffSStefano Zampini 
410a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
411a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
412a13144ffSStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
413a13144ffSStefano Zampini 
414a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
415a13144ffSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
416a13144ffSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
417a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
418a13144ffSStefano Zampini 
419a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
420a13144ffSStefano Zampini   maxsize = 0;
421a13144ffSStefano Zampini   ierr    = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
422a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
423a13144ffSStefano Zampini     PetscInt size,mark = i+1;
424a13144ffSStefano Zampini 
425a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
426a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
427a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
428a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
429a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
430a13144ffSStefano Zampini   }
431a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
432a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
433a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
434a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
435a13144ffSStefano Zampini   if (print) {
436a13144ffSStefano Zampini    ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
437a13144ffSStefano Zampini    ierr = ISView(primals,NULL);CHKERRQ(ierr);
438a13144ffSStefano Zampini   }
439a13144ffSStefano Zampini 
440a13144ffSStefano Zampini   /* Find coarse edge endpoints */
441a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
442a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
443a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
444a13144ffSStefano Zampini     PetscInt mark = i+1,size;
445a13144ffSStefano Zampini 
446a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
447a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
448a13144ffSStefano Zampini     if (print) {
449a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
450a13144ffSStefano Zampini       ISView(eedges[i],NULL);
451a13144ffSStefano Zampini     }
452a13144ffSStefano Zampini     for (j=0;j<size;j++) {
453a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
454a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
455a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
456a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
457a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
458a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
459a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
460a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      candidate? %d\n",(PetscBool)(PetscBTLookup(btvcand,jj[k])));
461a13144ffSStefano Zampini           PetscInt  k2;
462a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
463a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
464a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        INSPECTING %d: count %d, mark %d (ref mark %d), special %d\n",jjt[k2],pcbddc->mat_graph->count[jjt[k2]],marks[jjt[k2]],mark,pcbddc->mat_graph->special_dof[jjt[k2]]);
465a13144ffSStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) ||
466a13144ffSStefano Zampini                 pcbddc->mat_graph->special_dof[jjt[k2]] == PCBDDCGRAPH_DIRICHLET_MARK) {
467a13144ffSStefano Zampini               corner = PETSC_TRUE;
468a13144ffSStefano Zampini               break;
469a13144ffSStefano Zampini             }
470a13144ffSStefano Zampini           }
471a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
472a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
473a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
474a13144ffSStefano Zampini           } else {
475a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
476a13144ffSStefano Zampini           }
477a13144ffSStefano Zampini         }
478a13144ffSStefano Zampini       }
479a13144ffSStefano Zampini     }
480a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
481a13144ffSStefano Zampini   }
482a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
483a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
484a13144ffSStefano Zampini 
485a13144ffSStefano Zampini   /* Reset marked primal dofs */
486a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
487a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
488a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
489a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
490a13144ffSStefano Zampini 
491a13144ffSStefano Zampini   /* Compute extended cols indices */
492a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG ,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
493a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
494a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
495a13144ffSStefano Zampini   i   *= maxsize;
496a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extcols);CHKERRQ(ierr);
497a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&emarks);CHKERRQ(ierr);
498a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
499a13144ffSStefano Zampini   eerr = PETSC_FALSE;
500a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
501a13144ffSStefano Zampini     PetscInt size;
502a13144ffSStefano Zampini 
503a13144ffSStefano Zampini     cum  = 0;
504a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
505a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
506a13144ffSStefano Zampini     for (j=0;j<size;j++) {
507a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
508a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
509a13144ffSStefano Zampini     }
510a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
511a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
512a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
513a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
514a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
515a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
516a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
517a13144ffSStefano Zampini     if (cum != size -1) {
518a13144ffSStefano Zampini       emarks[i] = 1;
519a13144ffSStefano Zampini       if (print) {
520a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
521a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
522a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
523a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
524a13144ffSStefano Zampini       }
525a13144ffSStefano Zampini       eerr = PETSC_TRUE;
526a13144ffSStefano Zampini     }
527a13144ffSStefano Zampini   }
528a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
529a13144ffSStefano Zampini   if (done) {
530a13144ffSStefano Zampini     PetscInt *newprimals;
531a13144ffSStefano Zampini 
532a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
533a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
534a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
535a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
536a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
537a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
538a13144ffSStefano Zampini       if (emarks[i]) {
539a13144ffSStefano Zampini         PetscInt size,mark = i+1;
540a13144ffSStefano Zampini 
541a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
542a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
543a13144ffSStefano Zampini         for (j=0;j<size;j++) {
544a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
545a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
546a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
547a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
548a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
549a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
550a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
551a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
552a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
553a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
554a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
555a13144ffSStefano Zampini                   /* finally set the new corners */
556a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
557a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
558a13144ffSStefano Zampini                   }
559a13144ffSStefano Zampini                 }
560a13144ffSStefano Zampini               }
561a13144ffSStefano Zampini             }
562a13144ffSStefano Zampini           }
563a13144ffSStefano Zampini         }
564a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
565a13144ffSStefano Zampini       }
566a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
567a13144ffSStefano Zampini     }
568a13144ffSStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
569a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
570a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
571a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
572a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
573a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
574a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
575a13144ffSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
576a13144ffSStefano Zampini 
577a13144ffSStefano Zampini     /* Mark again */
578a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
579a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
580a13144ffSStefano Zampini       PetscInt size,mark = i+1;
581a13144ffSStefano Zampini 
582a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
583a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
584a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
585a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
586a13144ffSStefano Zampini     }
587a13144ffSStefano Zampini     if (print) {
588a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
589a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
590a13144ffSStefano Zampini     }
591a13144ffSStefano Zampini 
592a13144ffSStefano Zampini     /* Recompute extended cols */
593a13144ffSStefano Zampini     eerr = PETSC_FALSE;
594a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
595a13144ffSStefano Zampini       PetscInt size;
596a13144ffSStefano Zampini 
597a13144ffSStefano Zampini       cum  = 0;
598a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
599a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
600a13144ffSStefano Zampini       for (j=0;j<size;j++) {
601a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
602a13144ffSStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) {
603a13144ffSStefano Zampini           if (!PetscBTLookup(btv,jj[k])) {
604a13144ffSStefano Zampini             extrow[cum++] = jj[k];
605a13144ffSStefano Zampini           }
606a13144ffSStefano Zampini         }
607a13144ffSStefano Zampini       }
608a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
609a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
610a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
611a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
612a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
613a13144ffSStefano Zampini       if (cum != size -1) {
614a13144ffSStefano Zampini         if (print) {
615a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
616a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
617a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
618a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
619a13144ffSStefano Zampini         }
620a13144ffSStefano Zampini         eerr = PETSC_TRUE;
621a13144ffSStefano Zampini       }
622a13144ffSStefano Zampini     }
623a13144ffSStefano Zampini   }
624a13144ffSStefano Zampini   ierr = MatRestoreRowIJ( lG,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
625a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
626a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
627a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
628a13144ffSStefano Zampini   /* an error should not occur at this point */
629a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
630a13144ffSStefano Zampini 
631a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
632a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
633a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
634a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
635a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
636a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
637a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
638a13144ffSStefano Zampini 
639a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
640a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
641a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
642a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
643a13144ffSStefano Zampini       if (emax < emarks[j]) {
644a13144ffSStefano Zampini         emax = emarks[j];
645a13144ffSStefano Zampini         eemax = j;
646a13144ffSStefano Zampini       }
647a13144ffSStefano Zampini     }
648a13144ffSStefano Zampini     /* not relevant for edges */
649a13144ffSStefano Zampini     if (!eemax) continue;
650a13144ffSStefano Zampini 
651a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
652a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
653a13144ffSStefano Zampini         SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %d and %d) connected through the %d nodal dof at edge dod %d\n",marks[jj[j]]-1,eemax,i,jj[j]);
654a13144ffSStefano Zampini       }
655a13144ffSStefano Zampini     }
656a13144ffSStefano Zampini   }
657a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
658a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
659a13144ffSStefano Zampini #endif
660a13144ffSStefano Zampini 
661a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
662a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
663a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
664a13144ffSStefano Zampini   extmem *= maxsize;
665a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
666a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
667a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
668a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
669a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
670a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
671a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
672a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
673a13144ffSStefano Zampini         mark = marks[jj[j]];
674a13144ffSStefano Zampini 
675a13144ffSStefano Zampini     /* not relevant */
676a13144ffSStefano Zampini     if (!mark) continue;
677a13144ffSStefano Zampini 
678a13144ffSStefano Zampini     /* import extended row */
679a13144ffSStefano Zampini     mark--;
680a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
681a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
682a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
683a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
684a13144ffSStefano Zampini #endif
685a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
686a13144ffSStefano Zampini     extrowcum[mark] += size;
687a13144ffSStefano Zampini   }
688a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
689a13144ffSStefano Zampini   cum  = 0;
690a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
691a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
692a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
693a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
694a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
695a13144ffSStefano Zampini   }
696a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
697a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
698a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
699a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
700a13144ffSStefano Zampini 
701a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
702a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
703a13144ffSStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
704a13144ffSStefano Zampini   for (i=0;i<maxsize;i++) vals[i] = 1.;
705a13144ffSStefano Zampini 
706a13144ffSStefano Zampini   /* Create vectors for quadrature rules */
707a13144ffSStefano Zampini   ierr = PetscMalloc1(nquads,&quads);CHKERRQ(ierr);
708a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
709a13144ffSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quads[i],NULL);CHKERRQ(ierr);
710a13144ffSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quads[i],el2g);CHKERRQ(ierr);
711a13144ffSStefano Zampini   }
712a13144ffSStefano Zampini   ierr = PCBDDCNullSpaceCreate(comm,PETSC_FALSE,nquads,quads,&nnsp);CHKERRQ(ierr);
713a13144ffSStefano Zampini 
714a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
715a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
716a13144ffSStefano Zampini   ierr = MatSetSizes(T,Le,Le,Ne,Ne);CHKERRQ(ierr);
717a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
718a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
719a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
720a13144ffSStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,el2g,el2g);CHKERRQ(ierr);
721a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
722a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
723a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
724a13144ffSStefano Zampini 
725a13144ffSStefano Zampini   /* Defaults to identity */
726a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
727a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
728a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
729a13144ffSStefano Zampini 
730a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
731a13144ffSStefano Zampini     Mat Gins = NULL, GKins = NULL;
732a13144ffSStefano Zampini 
733a13144ffSStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],&Gins,&GKins,work,rwork);CHKERRQ(ierr);
734a13144ffSStefano Zampini     if (Gins && GKins) {
735a13144ffSStefano Zampini       PetscScalar    *data;
736a13144ffSStefano Zampini       const PetscInt *rows,*cols;
737a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
738a13144ffSStefano Zampini 
739a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
740a13144ffSStefano Zampini       /* H1 */
741a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
742a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
743a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
744a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
745a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
746a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
747a13144ffSStefano Zampini       /* complement */
748a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
749a13144ffSStefano Zampini       if (ncc > nquads-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet supported ncc %d nquads %d",ncc,nquads);
750a13144ffSStefano 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);
751a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
752a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
753a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
754a13144ffSStefano Zampini       /* Gins kernel quadratures */
755a13144ffSStefano Zampini       for (j=0;j<ncc;j++) {
756a13144ffSStefano Zampini         ierr = VecSetValueLocal(quads[j],cols[nch+j],1.,INSERT_VALUES);CHKERRQ(ierr);
757a13144ffSStefano Zampini       }
758a13144ffSStefano Zampini       /* H1 average */
759a13144ffSStefano Zampini       ierr = VecSetValuesLocal(quads[nquads-1],nch,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
760a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
761a13144ffSStefano Zampini     }
762a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
763a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
764a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
765a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
766a13144ffSStefano Zampini   }
767a13144ffSStefano Zampini 
768a13144ffSStefano Zampini   /* Start assembling */
769a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
770a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
771a13144ffSStefano Zampini     ierr = VecAssemblyBegin(quads[i]);CHKERRQ(ierr);
772a13144ffSStefano Zampini   }
773a13144ffSStefano Zampini 
774a13144ffSStefano Zampini   /* Free */
775a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
776a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
777a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
778a13144ffSStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
779a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
780a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
781a13144ffSStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
782a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
783a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
784a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
785a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
786a13144ffSStefano Zampini 
787a13144ffSStefano Zampini   /* Complete assembling */
788a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
789a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
790a13144ffSStefano Zampini     ierr = VecAssemblyEnd(quads[i]);CHKERRQ(ierr);
791a13144ffSStefano Zampini   }
792a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
793a13144ffSStefano Zampini     ierr = VecDestroy(&quads[i]);CHKERRQ(ierr);
794a13144ffSStefano Zampini   }
795a13144ffSStefano Zampini   ierr = PetscFree(quads);CHKERRQ(ierr);
796a13144ffSStefano Zampini 
797a13144ffSStefano Zampini   /* tell PCBDDC the topography has been analyzed */
798a13144ffSStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
799a13144ffSStefano Zampini 
800a13144ffSStefano Zampini   /* set change of basis */
801a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
802a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
803a13144ffSStefano Zampini 
804a13144ffSStefano Zampini   /* set quadratures */
805a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
806a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
807a13144ffSStefano Zampini 
808a13144ffSStefano Zampini   PetscFunctionReturn(0);
809a13144ffSStefano Zampini }
810a13144ffSStefano Zampini 
811d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
812d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
813d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
814d8203eabSStefano Zampini #undef __FUNCT__
815d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
816d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
817d8203eabSStefano Zampini {
818d8203eabSStefano Zampini   PetscErrorCode ierr;
819d8203eabSStefano Zampini   PetscInt       i;
820d8203eabSStefano Zampini 
821d8203eabSStefano Zampini   PetscFunctionBegin;
822d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
823d8203eabSStefano Zampini     PetscInt first,last;
824d8203eabSStefano Zampini 
825d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
82686fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
827d8203eabSStefano Zampini     if (i>=first && i < last) {
828d8203eabSStefano Zampini       PetscScalar *data;
829d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
830d8203eabSStefano Zampini       if (!has_const) {
831d8203eabSStefano Zampini         data[i-first] = 1.;
832d8203eabSStefano Zampini       } else {
83386fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
83486fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
835d8203eabSStefano Zampini       }
836d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
837d8203eabSStefano Zampini     }
838d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
839d8203eabSStefano Zampini   }
840d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
841d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
842d8203eabSStefano Zampini     PetscInt first,last;
843d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
844d8203eabSStefano Zampini     if (i>=first && i < last) {
845d8203eabSStefano Zampini       PetscScalar *data;
846d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
847d8203eabSStefano Zampini       if (!has_const) {
848d8203eabSStefano Zampini         data[i-first] = 0.;
849d8203eabSStefano Zampini       } else {
85086fa73c5SStefano Zampini         data[2*i-first] = 0.;
85186fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
852d8203eabSStefano Zampini       }
853d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
854d8203eabSStefano Zampini     }
855d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
856d8203eabSStefano Zampini   }
857d8203eabSStefano Zampini   PetscFunctionReturn(0);
858d8203eabSStefano Zampini }
859d8203eabSStefano Zampini 
860669cc0f4SStefano Zampini #undef __FUNCT__
861669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
8628ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
863669cc0f4SStefano Zampini {
864a198735bSStefano Zampini   Mat                    loc_divudotp;
865fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
8668ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
867669cc0f4SStefano Zampini   IS                     *faces,*edges;
868669cc0f4SStefano Zampini   PetscScalar            *vals;
869669cc0f4SStefano Zampini   const PetscScalar      *array;
870669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
8711ae86dd6SStefano Zampini   PetscMPIInt            rank;
872a198735bSStefano Zampini   PetscErrorCode         ierr;
873669cc0f4SStefano Zampini 
874669cc0f4SStefano Zampini   PetscFunctionBegin;
875669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
876669cc0f4SStefano Zampini   if (graph->twodim) {
877669cc0f4SStefano Zampini     lmaxneighs = 2;
878669cc0f4SStefano Zampini   } else {
879669cc0f4SStefano Zampini     lmaxneighs = 1;
880669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
881669cc0f4SStefano Zampini       const PetscInt *idxs;
882669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
883669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
884669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
885669cc0f4SStefano Zampini     }
886669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
887669cc0f4SStefano Zampini   }
888669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
889669cc0f4SStefano Zampini   maxsize = 0;
890669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
891669cc0f4SStefano Zampini     PetscInt nn;
892669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
893669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
894669cc0f4SStefano Zampini   }
895669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
896669cc0f4SStefano Zampini     PetscInt nn;
897669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
898669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
899669cc0f4SStefano Zampini   }
900669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
901669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
902669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
9038ae0ca82SStefano Zampini   if (!transpose) {
9048ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
9058ae0ca82SStefano Zampini   } else {
9068ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
9078ae0ca82SStefano Zampini   }
908669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
9091ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
910d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
911669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
9128ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
913669cc0f4SStefano Zampini   }
914d8203eabSStefano Zampini 
915669cc0f4SStefano Zampini   /* compute local quad vec */
916a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
9178ae0ca82SStefano Zampini   if (!transpose) {
918a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
9198ae0ca82SStefano Zampini   } else {
9208ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
9218ae0ca82SStefano Zampini   }
922669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
9238ae0ca82SStefano Zampini   if (!transpose) {
924a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
9258ae0ca82SStefano Zampini   } else {
9268ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
9278ae0ca82SStefano Zampini   }
928fa23a32eSStefano Zampini   if (vl2l) {
929fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
930fa23a32eSStefano Zampini   } else {
931fa23a32eSStefano Zampini     vins = v;
932fa23a32eSStefano Zampini   }
933fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
934669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
9359a962809SStefano Zampini 
9361ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
9371ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
938669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
939669cc0f4SStefano Zampini     const PetscInt    *idxs;
940669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
941669cc0f4SStefano Zampini 
942669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
943669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
944669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
9451ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
946669cc0f4SStefano Zampini     idx = -(idx+1);
947669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
948669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
949669cc0f4SStefano Zampini   }
950669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
951669cc0f4SStefano Zampini     const PetscInt    *idxs;
952669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
953669cc0f4SStefano Zampini 
954669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
955669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
956669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
9571ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
958669cc0f4SStefano Zampini     idx = -(idx+1);
959669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
960669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
961669cc0f4SStefano Zampini   }
962c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
963fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
964fa23a32eSStefano Zampini   if (vl2l) {
965fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
966fa23a32eSStefano Zampini   }
967669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
968669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
969669cc0f4SStefano Zampini 
970669cc0f4SStefano Zampini   /* assemble near null space */
971669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
972669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
973669cc0f4SStefano Zampini   }
974669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
975669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
976669cc0f4SStefano Zampini   }
977669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
978669cc0f4SStefano Zampini   PetscFunctionReturn(0);
979669cc0f4SStefano Zampini }
980669cc0f4SStefano Zampini 
981669cc0f4SStefano Zampini 
982a3df083aSStefano Zampini #undef __FUNCT__
9831f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
9841f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
9851f4df5f7SStefano Zampini {
9861f4df5f7SStefano Zampini   PetscErrorCode ierr;
9871f4df5f7SStefano Zampini   Vec            local,global;
9881f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9891f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
9901f4df5f7SStefano Zampini 
9911f4df5f7SStefano Zampini   PetscFunctionBegin;
9921f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
9931f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
9941f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
9951f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
9961f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
9971f4df5f7SStefano Zampini       PetscInt i;
9981f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
9991f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
10001f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
10011f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
10021f4df5f7SStefano Zampini       }
10031f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
10041f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
10051f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
10061f4df5f7SStefano Zampini     }
10071f4df5f7SStefano Zampini   } else {
1008986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
10091f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1010986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1011986cdee1SStefano Zampini       if (i > 1) {
1012986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
10131f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
10141f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
10151f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
10161f4df5f7SStefano Zampini         }
10171f4df5f7SStefano Zampini       }
10181f4df5f7SStefano Zampini     }
1019986cdee1SStefano Zampini   }
10201f4df5f7SStefano Zampini 
10211f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
10221f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
10231f4df5f7SStefano Zampini   }
10241f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
10251f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
10261f4df5f7SStefano Zampini   }
10271f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
10281f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
10291f4df5f7SStefano Zampini   }
10301f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
10311f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
10321f4df5f7SStefano Zampini   PetscFunctionReturn(0);
10331f4df5f7SStefano Zampini }
10341f4df5f7SStefano Zampini 
10351f4df5f7SStefano Zampini #undef __FUNCT__
10363e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
10373e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
10383e589ea0SStefano Zampini {
10393e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
10403e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
10413e589ea0SStefano Zampini   PetscErrorCode    ierr;
10423e589ea0SStefano Zampini 
10433e589ea0SStefano Zampini   PetscFunctionBegin;
10443e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
10453e589ea0SStefano Zampini     PetscFunctionReturn(0);
10463e589ea0SStefano Zampini   }
10473e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
10483e589ea0SStefano Zampini     Vec swap;
10493e589ea0SStefano Zampini 
10503e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
10513e589ea0SStefano Zampini     swap = pcbddc->work_change;
10523e589ea0SStefano Zampini     pcbddc->work_change = r;
10533e589ea0SStefano Zampini     r = swap;
10543e589ea0SStefano Zampini   }
10553e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10563e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10573e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
10583e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
10593e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10603e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10613e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
10623e589ea0SStefano Zampini     Vec swap;
10633e589ea0SStefano Zampini 
10643e589ea0SStefano Zampini     swap = r;
10653e589ea0SStefano Zampini     r = pcbddc->work_change;
10663e589ea0SStefano Zampini     pcbddc->work_change = swap;
10673e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
10683e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
10693e589ea0SStefano Zampini   }
10703e589ea0SStefano Zampini   PetscFunctionReturn(0);
10713e589ea0SStefano Zampini }
10723e589ea0SStefano Zampini 
10733e589ea0SStefano Zampini #undef __FUNCT__
1074a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1075a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1076a3df083aSStefano Zampini {
1077a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1078a3df083aSStefano Zampini   PetscErrorCode          ierr;
1079a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1080a3df083aSStefano Zampini 
1081a3df083aSStefano Zampini   PetscFunctionBegin;
1082a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1083a3df083aSStefano Zampini   if (transpose) {
1084a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1085a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1086a3df083aSStefano Zampini   } else {
1087a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1088a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1089a3df083aSStefano Zampini   }
1090a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1091a3df083aSStefano Zampini   if (apply_right) {
1092a3df083aSStefano Zampini     const PetscScalar *ax;
1093a3df083aSStefano Zampini     PetscInt          nl,i;
1094a3df083aSStefano Zampini 
1095a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1096a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1097a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1098a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
1099a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1100a3df083aSStefano Zampini       PetscScalar    sum,val;
1101a3df083aSStefano Zampini       const PetscInt *idxs;
1102a3df083aSStefano Zampini       PetscInt       nz,j;
1103a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1104a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1105a3df083aSStefano Zampini       sum = 0.;
1106a3df083aSStefano Zampini       if (ctx->apply_p0) {
1107a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1108a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1109a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1110a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1111a3df083aSStefano Zampini         }
1112a3df083aSStefano Zampini       } else {
1113a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1114a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1115a3df083aSStefano Zampini         }
1116a3df083aSStefano Zampini       }
1117a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1118a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1119a3df083aSStefano Zampini     }
1120a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1121a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1122a3df083aSStefano Zampini   }
1123a3df083aSStefano Zampini   if (transpose) {
1124a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1125a3df083aSStefano Zampini   } else {
1126a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1127a3df083aSStefano Zampini   }
1128a3df083aSStefano Zampini   if (reset_x) {
1129a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1130a3df083aSStefano Zampini   }
1131a3df083aSStefano Zampini   if (apply_left) {
1132a3df083aSStefano Zampini     PetscScalar *ay;
1133a3df083aSStefano Zampini     PetscInt    i;
1134a3df083aSStefano Zampini 
1135a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1136a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1137a3df083aSStefano Zampini       PetscScalar    sum,val;
1138a3df083aSStefano Zampini       const PetscInt *idxs;
1139a3df083aSStefano Zampini       PetscInt       nz,j;
1140a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1141a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1142a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1143a3df083aSStefano Zampini       if (ctx->apply_p0) {
1144a3df083aSStefano Zampini         sum = 0.;
1145a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1146a3df083aSStefano Zampini           sum += ay[idxs[j]];
1147a3df083aSStefano Zampini           ay[idxs[j]] += val;
1148a3df083aSStefano Zampini         }
1149a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1150a3df083aSStefano Zampini       } else {
1151a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1152a3df083aSStefano Zampini           ay[idxs[j]] += val;
1153a3df083aSStefano Zampini         }
1154a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1155a3df083aSStefano Zampini       }
1156a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1157a3df083aSStefano Zampini     }
1158a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1159a3df083aSStefano Zampini   }
1160a3df083aSStefano Zampini   PetscFunctionReturn(0);
1161a3df083aSStefano Zampini }
1162a3df083aSStefano Zampini 
1163a3df083aSStefano Zampini #undef __FUNCT__
1164a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1165a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1166a3df083aSStefano Zampini {
1167a3df083aSStefano Zampini   PetscErrorCode ierr;
1168a3df083aSStefano Zampini 
1169a3df083aSStefano Zampini   PetscFunctionBegin;
1170a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1171a3df083aSStefano Zampini   PetscFunctionReturn(0);
1172a3df083aSStefano Zampini }
1173a3df083aSStefano Zampini 
1174a3df083aSStefano Zampini #undef __FUNCT__
1175a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1176a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1177a3df083aSStefano Zampini {
1178a3df083aSStefano Zampini   PetscErrorCode ierr;
1179a3df083aSStefano Zampini 
1180a3df083aSStefano Zampini   PetscFunctionBegin;
1181a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1182a3df083aSStefano Zampini   PetscFunctionReturn(0);
1183a3df083aSStefano Zampini }
1184a3df083aSStefano Zampini 
1185a3df083aSStefano Zampini #undef __FUNCT__
1186a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1187a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1188a3df083aSStefano Zampini {
1189a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1190a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1191a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1192a3df083aSStefano Zampini   PetscErrorCode          ierr;
1193a3df083aSStefano Zampini 
1194a3df083aSStefano Zampini   PetscFunctionBegin;
1195a3df083aSStefano Zampini   if (!restore) {
11961dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1197a3df083aSStefano Zampini     PetscScalar        *work;
1198b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1199a3df083aSStefano Zampini 
12009a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
12019a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1202a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1203a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1204a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1205a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1206a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1207a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1208a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1209a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1210a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1211a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1212a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1213a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1214059032f7SStefano Zampini     if (reuse) {
1215a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
12161dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1217059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1218059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1219059032f7SStefano Zampini       PetscInt               i;
1220059032f7SStefano Zampini 
1221059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1222059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1223059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1224059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1225059032f7SStefano Zampini       }
1226059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
12271dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1228059032f7SStefano Zampini     }
1229a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1230a3df083aSStefano Zampini     ctx->work = work;
1231a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1232a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1233a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1234a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1235a3df083aSStefano Zampini 
1236a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1237a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1238a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1239a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1240a3df083aSStefano Zampini   } else {
12411dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
12421dd7afcfSStefano Zampini       PetscFunctionReturn(0);
12431dd7afcfSStefano Zampini     }
1244a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1245a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1246a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
12471dd7afcfSStefano Zampini     ctx->A = NULL;
12481dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
12491dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
12501dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
12511dd7afcfSStefano Zampini     if (ctx->free) {
1252059032f7SStefano Zampini       PetscInt i;
12531dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1254059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1255059032f7SStefano Zampini       }
1256059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1257059032f7SStefano Zampini     }
1258a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1259a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1260a3df083aSStefano Zampini   }
1261a3df083aSStefano Zampini   PetscFunctionReturn(0);
1262a3df083aSStefano Zampini }
1263a3df083aSStefano Zampini 
1264a3df083aSStefano Zampini /* used just in bddc debug mode */
1265a3df083aSStefano Zampini #undef __FUNCT__
1266a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1267a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1268a3df083aSStefano Zampini {
1269a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1270a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1271a3df083aSStefano Zampini   Mat            An;
1272a3df083aSStefano Zampini   PetscErrorCode ierr;
1273a3df083aSStefano Zampini 
1274a3df083aSStefano Zampini   PetscFunctionBegin;
1275a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1276a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1277a3df083aSStefano Zampini   if (is1) {
1278a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1279a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1280a3df083aSStefano Zampini   } else {
1281a3df083aSStefano Zampini     *B = An;
1282a3df083aSStefano Zampini   }
1283a3df083aSStefano Zampini   PetscFunctionReturn(0);
1284a3df083aSStefano Zampini }
1285a3df083aSStefano Zampini 
12861cf9b237SStefano Zampini /* TODO: add reuse flag */
12871cf9b237SStefano Zampini #undef __FUNCT__
12881cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
12891cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
12901cf9b237SStefano Zampini {
12911cf9b237SStefano Zampini   Mat            Bt;
12921cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
12931cf9b237SStefano Zampini   const PetscInt *ii,*ij;
12941cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
12951cf9b237SStefano Zampini   PetscBool      flg_row;
12961cf9b237SStefano Zampini   PetscErrorCode ierr;
12971cf9b237SStefano Zampini 
12981cf9b237SStefano Zampini   PetscFunctionBegin;
12991cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
13001cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
13011cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
13021cf9b237SStefano Zampini   nnz = n;
13031cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
13041cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
13051cf9b237SStefano Zampini   }
13061cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
13071cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
13081cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
13091cf9b237SStefano Zampini   nnz = 0;
13101cf9b237SStefano Zampini   bii[0] = 0;
13111cf9b237SStefano Zampini   for (i=0;i<n;i++) {
13121cf9b237SStefano Zampini     PetscInt j;
13131cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
13141cf9b237SStefano Zampini       PetscScalar entry = a[j];
13151cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
13161cf9b237SStefano Zampini         bij[nnz] = ij[j];
13171cf9b237SStefano Zampini         bdata[nnz] = entry;
13181cf9b237SStefano Zampini         nnz++;
13191cf9b237SStefano Zampini       }
13201cf9b237SStefano Zampini     }
13211cf9b237SStefano Zampini     bii[i+1] = nnz;
13221cf9b237SStefano Zampini   }
13231cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
13241cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
13251cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
13261cf9b237SStefano Zampini   {
13271cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
13281cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
13291cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
13301cf9b237SStefano Zampini   }
13311cf9b237SStefano Zampini   *B = Bt;
13321cf9b237SStefano Zampini   PetscFunctionReturn(0);
13331cf9b237SStefano Zampini }
13341cf9b237SStefano Zampini 
1335674ae819SStefano Zampini #undef __FUNCT__
13364f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
13374f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
13384f1b2e48SStefano Zampini {
13394f1b2e48SStefano Zampini   Mat                    B;
13404f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
13414f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
13424f1b2e48SStefano Zampini   PCBDDCGraph            graph;
13434f1b2e48SStefano Zampini   PetscInt               i,n;
13444f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
13454f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
13464f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
13474f1b2e48SStefano Zampini   PetscErrorCode         ierr;
13484f1b2e48SStefano Zampini 
13494f1b2e48SStefano Zampini   PetscFunctionBegin;
135063c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
135163c961adSStefano Zampini     *ncc = 0;
135263c961adSStefano Zampini     *cc = NULL;
135363c961adSStefano Zampini     PetscFunctionReturn(0);
135463c961adSStefano Zampini   }
13554f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
13564f1b2e48SStefano Zampini   if (!isseqaij && filter) {
13571cf9b237SStefano Zampini     PetscBool isseqdense;
13581cf9b237SStefano Zampini 
13591cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
13601cf9b237SStefano Zampini     if (!isseqdense) {
13614f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
13621cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
13631cf9b237SStefano Zampini       PetscScalar *array;
13641cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
13651cf9b237SStefano Zampini 
13661cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
13671cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
13681cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
13691cf9b237SStefano Zampini       for (i=0;i<n;i++) {
13701cf9b237SStefano Zampini         PetscInt j;
13711cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
13721cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
13731cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
13741cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
13751cf9b237SStefano Zampini         }
13761cf9b237SStefano Zampini       }
13771cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
13789d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
13791cf9b237SStefano Zampini     }
13804f1b2e48SStefano Zampini   } else {
13814f1b2e48SStefano Zampini     B = A;
13824f1b2e48SStefano Zampini   }
13834f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
13844f1b2e48SStefano Zampini 
13854f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
13864f1b2e48SStefano Zampini   if (filter) {
13874f1b2e48SStefano Zampini     PetscScalar *data;
13884f1b2e48SStefano Zampini     PetscInt    j,cum;
13894f1b2e48SStefano Zampini 
13904f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
13914f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
13924f1b2e48SStefano Zampini     cum = 0;
13934f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
13944f1b2e48SStefano Zampini       PetscInt t;
13954f1b2e48SStefano Zampini 
13964f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
13974f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
13984f1b2e48SStefano Zampini           continue;
13994f1b2e48SStefano Zampini         }
14004f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
14014f1b2e48SStefano Zampini       }
14024f1b2e48SStefano Zampini       t = xadj_filtered[i];
14034f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
14044f1b2e48SStefano Zampini       cum += t;
14054f1b2e48SStefano Zampini     }
14064f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
14074f1b2e48SStefano Zampini   } else {
14084f1b2e48SStefano Zampini     xadj_filtered = NULL;
14094f1b2e48SStefano Zampini     adjncy_filtered = NULL;
14104f1b2e48SStefano Zampini   }
14114f1b2e48SStefano Zampini 
14124f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
14134f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
14144f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
14154f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
14164f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1417*be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
14184f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
14194f1b2e48SStefano Zampini   if (xadj_filtered) {
14204f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
14214f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
14224f1b2e48SStefano Zampini   } else {
14234f1b2e48SStefano Zampini     graph->xadj = xadj;
14244f1b2e48SStefano Zampini     graph->adjncy = adjncy;
14254f1b2e48SStefano Zampini   }
14264f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
14274f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
14284f1b2e48SStefano Zampini   /* partial clean up */
14294f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
14304f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
14311cf9b237SStefano Zampini   if (A != B) {
14324f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
14334f1b2e48SStefano Zampini   }
14344f1b2e48SStefano Zampini 
14354f1b2e48SStefano Zampini   /* get back data */
14361cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
14371cf9b237SStefano Zampini   if (cc) {
14384f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
14394f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
14404f1b2e48SStefano 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);
14414f1b2e48SStefano Zampini     }
14424f1b2e48SStefano Zampini     *cc = cc_n;
14431cf9b237SStefano Zampini   }
14444f1b2e48SStefano Zampini   /* clean up graph */
14454f1b2e48SStefano Zampini   graph->xadj = 0;
14464f1b2e48SStefano Zampini   graph->adjncy = 0;
14474f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
14484f1b2e48SStefano Zampini   PetscFunctionReturn(0);
14494f1b2e48SStefano Zampini }
14504f1b2e48SStefano Zampini 
14514f1b2e48SStefano Zampini #undef __FUNCT__
14525408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
14535408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
14545408967cSStefano Zampini {
14555408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14565408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1457dee84bffSStefano Zampini   IS             dirIS = NULL;
14584f1b2e48SStefano Zampini   PetscInt       i;
14595408967cSStefano Zampini   PetscErrorCode ierr;
14605408967cSStefano Zampini 
14615408967cSStefano Zampini   PetscFunctionBegin;
1462dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
14635408967cSStefano Zampini   if (zerodiag) {
14645408967cSStefano Zampini     Mat            A;
14655408967cSStefano Zampini     Vec            vec3_N;
14665408967cSStefano Zampini     PetscScalar    *vals;
14675408967cSStefano Zampini     const PetscInt *idxs;
1468d12d3064SStefano Zampini     PetscInt       nz,*count;
14695408967cSStefano Zampini 
14705408967cSStefano Zampini     /* p0 */
14715408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
14725408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
14735408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
14745408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
14754f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
14765408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
14775408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
14785408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
14795408967cSStefano Zampini     /* v_I */
14805408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
14815408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
14825408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
14835408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
14845408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
14855408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
14865408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
14875408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
14885408967cSStefano Zampini     if (dirIS) {
14895408967cSStefano Zampini       PetscInt n;
14905408967cSStefano Zampini 
14915408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
14925408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
14935408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
14945408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
14955408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
14965408967cSStefano Zampini     }
14975408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
14985408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
14995408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
15005408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1501669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
15025408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
15035408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
15049a962809SStefano 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]));
15055408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
15065408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1507d12d3064SStefano Zampini 
1508d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1509d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1510d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1511d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1512d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1513d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
15149a962809SStefano 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]);
1515d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1516d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
15175408967cSStefano Zampini   }
1518dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
15195408967cSStefano Zampini 
15205408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
15215408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
15224f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
15235408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
15244f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
15255408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1526f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1527f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1528f2a566d8SStefano 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);
1529f2a566d8SStefano Zampini   }
15305408967cSStefano Zampini   PetscFunctionReturn(0);
15315408967cSStefano Zampini }
15325408967cSStefano Zampini 
15335408967cSStefano Zampini #undef __FUNCT__
1534339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1535339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1536339f8db1SStefano Zampini {
1537339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
15384f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1539b0f5fe93SStefano Zampini   PetscInt       nz,n;
15401f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
15414f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1542339f8db1SStefano Zampini   PetscErrorCode ierr;
1543339f8db1SStefano Zampini 
1544339f8db1SStefano Zampini   PetscFunctionBegin;
15459f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
15469f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1547a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1548a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1549a3df083aSStefano Zampini   }
1550a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1551a3df083aSStefano Zampini   pcbddc->benign_n = 0;
15521ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
15534f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
15544f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
15554f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
15561ae86dd6SStefano Zampini      since the local Schur complements are already SPD
15574f1b2e48SStefano Zampini   */
15584f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
15594f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
156040fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
15614f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
15624f1b2e48SStefano Zampini 
15634f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
15644f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
15654f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
15664f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1567ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
156840fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
156940fa8d13SStefano Zampini     if (!sorted) {
157040fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
157140fa8d13SStefano Zampini     }
157240fa8d13SStefano Zampini   } else {
157340fa8d13SStefano Zampini     pressures = NULL;
157440fa8d13SStefano Zampini   }
157597d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
157697d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
157727b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
157897d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1579339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1580339f8db1SStefano Zampini   if (!sorted) {
1581339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1582339f8db1SStefano Zampini   }
1583339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
15844f1b2e48SStefano Zampini   if (!nz) {
15854f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
15864f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
158740fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
158840fa8d13SStefano Zampini   }
15894f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
15904f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
15914f1b2e48SStefano Zampini   zerodiag_subs = NULL;
15924f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
15931f4df5f7SStefano Zampini   n_interior_dofs = 0;
15941f4df5f7SStefano Zampini   interior_dofs = NULL;
15951f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
15961f4df5f7SStefano Zampini     PetscInt n,i,j;
15971f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
15981f4df5f7SStefano Zampini     PetscInt *iwork;
15991f4df5f7SStefano Zampini 
16001f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
16011f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16021f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
16031f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
160490648384SStefano Zampini     for (i=1;i<n_neigh;i++)
16051f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
16061f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
16071f4df5f7SStefano Zampini     for (i=0;i<n;i++)
16081f4df5f7SStefano Zampini       if (!iwork[i])
16091f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
16101f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
16111f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16121f4df5f7SStefano Zampini   }
16134f1b2e48SStefano Zampini   if (has_null_pressures) {
16144f1b2e48SStefano Zampini     IS             *subs;
16151f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
16161f4df5f7SStefano Zampini     const PetscInt *idxs;
16171f4df5f7SStefano Zampini     PetscScalar    *array;
16181f4df5f7SStefano Zampini     Vec            *work;
16191f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
16204f1b2e48SStefano Zampini 
16214f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
16224f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
16231f4df5f7SStefano 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) */
16241f4df5f7SStefano Zampini     if (pcbddc->current_level) {
16251f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
16261f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
16271f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
16281f4df5f7SStefano Zampini       /* work[0] = 1_p */
16291f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
16301f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
16311f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
16321f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
16331f4df5f7SStefano Zampini       /* work[0] = 1_v */
16341f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
16351f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
16361f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
16371f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
16381f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
16391f4df5f7SStefano Zampini     }
16404f1b2e48SStefano Zampini     if (nsubs > 1) {
16414f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
16424f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
16434f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
16444f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
16454f1b2e48SStefano Zampini         PetscInt               nl;
16464f1b2e48SStefano Zampini 
16474f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
16484f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
16494f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
16504f1b2e48SStefano Zampini         if (nl) {
16514f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
16524f1b2e48SStefano Zampini 
16531f4df5f7SStefano Zampini           if (pcbddc->current_level) {
16541f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
16551f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
16561f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
16571f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
16581f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
16591f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
16601f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
16611f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
16621f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
16631f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
16641f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
16651f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
16661f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
16671f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
16681f4df5f7SStefano Zampini                 break;
16691f4df5f7SStefano Zampini               }
16701f4df5f7SStefano Zampini             }
16711f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
16721f4df5f7SStefano Zampini           }
16731f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
16741f4df5f7SStefano Zampini             IS       t_bc;
16751f4df5f7SStefano Zampini             PetscInt nzb;
16761f4df5f7SStefano Zampini 
16771f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
16781f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
16791f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
16801f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
16811f4df5f7SStefano Zampini           }
16821f4df5f7SStefano Zampini           if (valid && pressures) {
16834f1b2e48SStefano Zampini             IS t_pressure_subs;
16844f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
16854f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
16864f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
16874f1b2e48SStefano Zampini           }
16884f1b2e48SStefano Zampini           if (valid) {
16894f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
16904f1b2e48SStefano Zampini             pcbddc->benign_n++;
16914f1b2e48SStefano Zampini           } else {
16924f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
16934f1b2e48SStefano Zampini           }
16944f1b2e48SStefano Zampini         }
16954f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
16964f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
16974f1b2e48SStefano Zampini       }
16984f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
16994f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
17001f4df5f7SStefano Zampini 
17011f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
17021f4df5f7SStefano Zampini         PetscInt nzb;
17031f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
17041f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
17051f4df5f7SStefano Zampini       }
17061f4df5f7SStefano Zampini       if (valid && pressures) {
17074f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
17084f1b2e48SStefano Zampini       }
17091f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
17101f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
17111f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
17121f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
17131f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
17141f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
17151f4df5f7SStefano Zampini               valid = PETSC_FALSE;
17161f4df5f7SStefano Zampini               break;
17171f4df5f7SStefano Zampini           }
17181f4df5f7SStefano Zampini         }
17191f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
17201f4df5f7SStefano Zampini       }
17214f1b2e48SStefano Zampini       if (valid) {
17224f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1723ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
17244f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
17254f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
17264f1b2e48SStefano Zampini       }
17274f1b2e48SStefano Zampini     }
17281f4df5f7SStefano Zampini     if (pcbddc->current_level) {
17291f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
17304f1b2e48SStefano Zampini     }
17311f4df5f7SStefano Zampini   }
17321f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
17334f1b2e48SStefano Zampini 
17344f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1735b9b0e38cSStefano Zampini     PetscInt n;
1736b9b0e38cSStefano Zampini 
17374f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
17384f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1739b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1740b9b0e38cSStefano Zampini     if (n) {
17414f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
17424f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
17434f1b2e48SStefano Zampini     }
1744b9b0e38cSStefano Zampini   }
17454f1b2e48SStefano Zampini 
17464f1b2e48SStefano Zampini   /* final check for null pressures */
17474f1b2e48SStefano Zampini   if (zerodiag && pressures) {
17484f1b2e48SStefano Zampini     PetscInt nz,np;
17494f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17504f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
17514f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
17524f1b2e48SStefano Zampini   }
17534f1b2e48SStefano Zampini 
17544f1b2e48SStefano Zampini   if (recompute_zerodiag) {
17554f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
17564f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
17574f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
17584f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
17594f1b2e48SStefano Zampini     } else {
17604f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
17614f1b2e48SStefano Zampini 
17624f1b2e48SStefano Zampini       nzn = 0;
17634f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
17644f1b2e48SStefano Zampini         PetscInt ns;
17654f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
17664f1b2e48SStefano Zampini         nzn += ns;
17674f1b2e48SStefano Zampini       }
17684f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
17694f1b2e48SStefano Zampini       nzn = 0;
17704f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
17714f1b2e48SStefano Zampini         PetscInt ns,*idxs;
17724f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
17734f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
17744f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
17754f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
17764f1b2e48SStefano Zampini         nzn += ns;
17774f1b2e48SStefano Zampini       }
17784f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
17794f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
17804f1b2e48SStefano Zampini     }
17814f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
17824f1b2e48SStefano Zampini   }
17834f1b2e48SStefano Zampini 
1784669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
1785a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
1786a198735bSStefano Zampini     Mat                    A,loc_divudotp;
1787a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
1788a198735bSStefano Zampini     IS                     row,col,isused = NULL;
1789a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
1790a198735bSStefano Zampini 
17911f4df5f7SStefano Zampini     if (pressures) {
17921f4df5f7SStefano Zampini       isused = pressures;
17931f4df5f7SStefano Zampini     } else {
17941f4df5f7SStefano Zampini       isused = zerodiag;
17951f4df5f7SStefano Zampini     }
1796a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
1797669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
17981ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
17991ae86dd6SStefano 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");
1800a198735bSStefano Zampini     n_isused = 0;
1801a198735bSStefano Zampini     if (isused) {
1802a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
1803a198735bSStefano Zampini     }
1804a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1805a198735bSStefano Zampini     st = st-n_isused;
18061ae86dd6SStefano Zampini     if (n) {
1807a198735bSStefano Zampini       const PetscInt *gidxs;
1808a198735bSStefano Zampini 
1809a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
1810a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
1811a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
1812a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
1813a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
1814a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
18151ae86dd6SStefano Zampini     } else {
1816a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
1817a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
1818a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
1819a198735bSStefano Zampini     }
1820a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
1821a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
1822a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
1823a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
1824a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
1825a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
1826a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
1827a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
1828a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1829a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
1830a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1831a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1832a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
1833a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
18341ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18351ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18361ae86dd6SStefano Zampini   }
1837b3afcdbeSStefano Zampini 
1838b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
18394f1b2e48SStefano Zampini   if (has_null_pressures) {
18404f1b2e48SStefano Zampini     IS             zerodiagc;
18414f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
18424f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
18434f1b2e48SStefano Zampini 
18444f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1845339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
1846339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
1847339f8db1SStefano Zampini     /* local change of basis for pressures */
1848339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
184997d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
1850339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
1851339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1852339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
18534f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
18544f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
18554f1b2e48SStefano Zampini       PetscInt nzs,j;
18564f1b2e48SStefano Zampini 
18574f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
18584f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
18594f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
18604f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
18614f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
18624f1b2e48SStefano Zampini     }
1863339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
1864339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1865339f8db1SStefano Zampini     /* set identity on velocities */
1866339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
1867339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
1868339f8db1SStefano Zampini     }
18694f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
18704f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
18719f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
18724f1b2e48SStefano 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);
1873339f8db1SStefano Zampini     /* set change on pressures */
18744f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
18754f1b2e48SStefano Zampini       PetscScalar *array;
18764f1b2e48SStefano Zampini       PetscInt    nzs;
18774f1b2e48SStefano Zampini 
18784f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
18794f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
18804f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
1881339f8db1SStefano Zampini         PetscScalar vals[2];
1882339f8db1SStefano Zampini         PetscInt    cols[2];
1883339f8db1SStefano Zampini 
1884339f8db1SStefano Zampini         cols[0] = idxs[i];
18854f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
1886339f8db1SStefano Zampini         vals[0] = 1.;
1887b0f5fe93SStefano Zampini         vals[1] = 1.;
18884f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1889339f8db1SStefano Zampini       }
18904f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
18914f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
18924f1b2e48SStefano Zampini       array[nzs-1] = 1.;
18934f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
18944f1b2e48SStefano Zampini       /* store local idxs for p0 */
18954f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
18964f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
1897339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
18984f1b2e48SStefano Zampini     }
1899339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1900339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1901a3df083aSStefano Zampini     /* project if needed */
1902a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
19031dd7afcfSStefano Zampini       Mat M;
19041dd7afcfSStefano Zampini 
19051dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1906339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
19071dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
19081dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
1909a3df083aSStefano Zampini     }
19104f1b2e48SStefano Zampini     /* store global idxs for p0 */
19114f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1912339f8db1SStefano Zampini   }
1913ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
19144f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
1915b0f5fe93SStefano Zampini 
1916b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
1917b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
191827b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
191927b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1920339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
1921339f8db1SStefano Zampini   PetscFunctionReturn(0);
1922339f8db1SStefano Zampini }
1923339f8db1SStefano Zampini 
1924339f8db1SStefano Zampini #undef __FUNCT__
1925015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
1926015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
1927efc2fbd9SStefano Zampini {
1928efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1929de9d7bd0SStefano Zampini   PetscScalar    *array;
1930efc2fbd9SStefano Zampini   PetscErrorCode ierr;
1931efc2fbd9SStefano Zampini 
1932efc2fbd9SStefano Zampini   PetscFunctionBegin;
1933efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
1934efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
19354f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1936efc2fbd9SStefano Zampini   }
1937de9d7bd0SStefano Zampini   if (get) {
1938efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
19394f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
19404f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1941efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1942de9d7bd0SStefano Zampini   } else {
1943de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1944de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1945de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1946de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1947efc2fbd9SStefano Zampini   }
1948efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1949efc2fbd9SStefano Zampini }
1950efc2fbd9SStefano Zampini 
1951efc2fbd9SStefano Zampini #undef __FUNCT__
1952c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1953c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1954c263805aSStefano Zampini {
1955c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1956c263805aSStefano Zampini   PetscErrorCode ierr;
1957c263805aSStefano Zampini 
1958c263805aSStefano Zampini   PetscFunctionBegin;
1959c263805aSStefano Zampini   /* TODO: add error checking
1960c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1961c263805aSStefano Zampini     - cannot push before pop.
19621c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1963c263805aSStefano Zampini   */
19644f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1965efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1966efc2fbd9SStefano Zampini   }
1967c263805aSStefano Zampini   if (pop) {
1968a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
19694f1b2e48SStefano Zampini       IS       is_p0;
19704f1b2e48SStefano Zampini       MatReuse reuse;
1971c263805aSStefano Zampini 
1972c263805aSStefano Zampini       /* extract B_0 */
19734f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
19744f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
19754f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
19764f1b2e48SStefano Zampini       }
19774f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
19784f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1979c263805aSStefano Zampini       /* remove rows and cols from local problem */
1980c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
198197d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
19824f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
19834f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1984a3df083aSStefano Zampini     } else {
1985a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1986a3df083aSStefano Zampini       PetscScalar *vals;
1987a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1988a3df083aSStefano Zampini 
1989a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1990a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1991a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
19920b5adadeSStefano Zampini         PetscInt *nnz;
1993a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1994a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1995a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1996331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1997331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1998331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1999331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2000331e053bSStefano Zampini         }
2001331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2002331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2003331e053bSStefano Zampini       }
2004a3df083aSStefano Zampini 
2005a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2006a3df083aSStefano Zampini         PetscScalar *array;
2007a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2008a3df083aSStefano Zampini 
2009a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2010a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2011a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2012a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2013a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2014a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2015a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2016a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2017a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2018a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2019a3df083aSStefano Zampini         cum = 0;
2020a3df083aSStefano Zampini         for (j=0;j<n;j++) {
202122db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2022a3df083aSStefano Zampini             vals[cum] = array[j];
2023a3df083aSStefano Zampini             idxs_ins[cum] = j;
2024a3df083aSStefano Zampini             cum++;
2025a3df083aSStefano Zampini           }
2026a3df083aSStefano Zampini         }
2027a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2028a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2029a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2030a3df083aSStefano Zampini       }
2031a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2032a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2033a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2034a3df083aSStefano Zampini     }
2035c263805aSStefano Zampini   } else { /* push */
2036a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
20374f1b2e48SStefano Zampini       PetscInt i;
20384f1b2e48SStefano Zampini 
20394f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20404f1b2e48SStefano Zampini         PetscScalar *B0_vals;
20414f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
20424f1b2e48SStefano Zampini 
20434f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
20444f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
20457b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
20464f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
20474f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
20484f1b2e48SStefano Zampini       }
2049c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2050c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2051a3df083aSStefano Zampini     } else {
2052a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2053a3df083aSStefano Zampini     }
2054c263805aSStefano Zampini   }
2055c263805aSStefano Zampini   PetscFunctionReturn(0);
2056c263805aSStefano Zampini }
2057c263805aSStefano Zampini 
2058c263805aSStefano Zampini #undef __FUNCT__
2059b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
206008122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2061b1b3d7a2SStefano Zampini {
2062b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
206308122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
206408122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
206508122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
206608122e43SStefano Zampini   PetscScalar     *work,lwork;
206708122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
206808122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
206908122e43SStefano Zampini   PetscReal       *eigs,thresh;
20701b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2071f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
207208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
207308122e43SStefano Zampini   PetscReal       *rwork;
207408122e43SStefano Zampini #endif
2075b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2076b1b3d7a2SStefano Zampini 
2077b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2078b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2079af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2080af25d912SStefano 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);
208106a4e24aSStefano Zampini 
2082fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2083fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2084fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2085fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
20861575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2087fd14bc51SStefano Zampini   }
2088fd14bc51SStefano Zampini 
2089e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2090e496cd5dSStefano 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);
2091e496cd5dSStefano Zampini   }
2092e496cd5dSStefano Zampini 
209308122e43SStefano Zampini   /* max size of subsets */
209408122e43SStefano Zampini   mss = 0;
209508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
209608122e43SStefano Zampini     PetscInt subset_size;
2097862806e4SStefano Zampini 
209808122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
209908122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
210008122e43SStefano Zampini   }
210108122e43SStefano Zampini 
210208122e43SStefano Zampini   /* min/max and threshold */
210308122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2104f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
210508122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2106f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2107f6f667cfSStefano Zampini   if (nmin) {
2108f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2109f6f667cfSStefano Zampini   }
211008122e43SStefano Zampini 
211108122e43SStefano Zampini   /* allocate lapack workspace */
211208122e43SStefano Zampini   cum = cum2 = 0;
211308122e43SStefano Zampini   maxneigs = 0;
211408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
211508122e43SStefano Zampini     PetscInt n,subset_size;
2116f6f667cfSStefano Zampini 
211708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
211808122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
21199162d606SStefano Zampini     cum += subset_size;
21209162d606SStefano Zampini     cum2 += subset_size*n;
212108122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
212208122e43SStefano Zampini   }
212308122e43SStefano Zampini   if (mss) {
21249ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
212508122e43SStefano Zampini       PetscBLASInt B_itype = 1;
212608122e43SStefano Zampini       PetscBLASInt B_N = mss;
21274c6709b3SStefano Zampini       PetscReal    zero = 0.0;
21284c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
212908122e43SStefano Zampini 
213008122e43SStefano Zampini       B_lwork = -1;
213108122e43SStefano Zampini       S = NULL;
213208122e43SStefano Zampini       St = NULL;
2133a58a30b4SStefano Zampini       eigs = NULL;
2134a58a30b4SStefano Zampini       eigv = NULL;
2135a58a30b4SStefano Zampini       B_iwork = NULL;
2136a58a30b4SStefano Zampini       B_ifail = NULL;
2137d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2138d1710679SStefano Zampini       rwork = NULL;
2139d1710679SStefano Zampini #endif
21408bec7fa6SStefano Zampini       thresh = 1.0;
214108122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
214208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
214308122e43SStefano 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));
214408122e43SStefano Zampini #else
214508122e43SStefano 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));
214608122e43SStefano Zampini #endif
214708122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
214808122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
214908122e43SStefano Zampini     } else {
215008122e43SStefano Zampini         /* TODO */
215108122e43SStefano Zampini     }
215208122e43SStefano Zampini   } else {
215308122e43SStefano Zampini     lwork = 0;
215408122e43SStefano Zampini   }
215508122e43SStefano Zampini 
215608122e43SStefano Zampini   nv = 0;
2157d62866d3SStefano 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) */
2158d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
215908122e43SStefano Zampini   }
21604c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2161f6f667cfSStefano Zampini   if (allocated_S_St) {
2162f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2163f6f667cfSStefano Zampini   }
2164f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
216508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
216608122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
216708122e43SStefano Zampini #endif
21689162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
21699162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
21709162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
217108122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
21729162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
217308122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
217408122e43SStefano Zampini 
217508122e43SStefano Zampini   maxneigs = 0;
217672b8c272SStefano Zampini   cum = cumarray = 0;
21779162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
21789162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2179d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
218008122e43SStefano Zampini     const PetscInt *idxs;
218108122e43SStefano Zampini 
2182d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
218308122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
218408122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
218508122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
218608122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
21879162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
21889162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
218908122e43SStefano Zampini     }
2190d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
219108122e43SStefano Zampini   }
219208122e43SStefano Zampini 
219308122e43SStefano Zampini   if (mss) { /* multilevel */
219408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
219508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
219608122e43SStefano Zampini   }
219708122e43SStefano Zampini 
2198ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
219908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
220008122e43SStefano Zampini     const PetscInt *idxs;
22019d54b7f4SStefano Zampini     PetscReal      upper,lower;
2202862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
220308122e43SStefano Zampini     PetscBLASInt   B_N;
2204aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
220508122e43SStefano Zampini 
22069d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
22079d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
22089d54b7f4SStefano Zampini       lower = thresh;
22099d54b7f4SStefano Zampini     } else {
22109d54b7f4SStefano Zampini       upper = 1./thresh;
22119d54b7f4SStefano Zampini       lower = 0.;
22129d54b7f4SStefano Zampini     }
2213862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2214ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2215f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2216f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
22179ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2218aff50787SStefano Zampini         PetscInt j,k;
2219aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2220aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2221aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
222208122e43SStefano Zampini         }
222308122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2224aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2225aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2226aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2227aff50787SStefano Zampini           }
222808122e43SStefano Zampini         }
222908122e43SStefano Zampini       } else {
223008122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
223108122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
223208122e43SStefano Zampini       }
22338bec7fa6SStefano Zampini     } else {
2234f6f667cfSStefano Zampini       S = Sarray + cumarray;
2235f6f667cfSStefano Zampini       St = Starray + cumarray;
22368bec7fa6SStefano Zampini     }
2237aff50787SStefano Zampini     /* see if we can save some work */
2238b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2239aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2240aff50787SStefano Zampini     }
2241aff50787SStefano Zampini 
2242b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2243aff50787SStefano Zampini       B_neigs = 0;
2244aff50787SStefano Zampini     } else {
22459ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
224608122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2247f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
22484c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
22499552c7c7SStefano Zampini         PetscInt     nmin_s;
2250b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
225108122e43SStefano Zampini 
2252fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
22538bec7fa6SStefano 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]]);
2254fd14bc51SStefano Zampini         }
2255d16cbb6bSStefano Zampini 
2256b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2257b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2258b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2259b7ab4a40SStefano Zampini         }
2260b7ab4a40SStefano Zampini 
226108122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2262b7ab4a40SStefano Zampini         if (compute_range) {
2263d16cbb6bSStefano Zampini 
2264d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
226508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
22669d54b7f4SStefano 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));
226708122e43SStefano Zampini #else
22689d54b7f4SStefano 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));
226908122e43SStefano Zampini #endif
2270b7ab4a40SStefano Zampini         } else if (!same_data) {
2271d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2272d16cbb6bSStefano Zampini           B_IL = 1;
2273d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
22749d54b7f4SStefano 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));
2275d16cbb6bSStefano Zampini #else
22769d54b7f4SStefano 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));
2277d16cbb6bSStefano Zampini #endif
2278b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2279b7ab4a40SStefano Zampini           PetscInt k;
2280b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2281b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2282b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2283b7ab4a40SStefano Zampini           nmin = nmax;
2284b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2285b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2286b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2287b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2288b7ab4a40SStefano Zampini           }
2289d16cbb6bSStefano Zampini         }
229008122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
229108122e43SStefano Zampini         if (B_ierr) {
22926c4ed002SBarry 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);
22936c4ed002SBarry 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);
22946c4ed002SBarry 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);
229508122e43SStefano Zampini         }
229608122e43SStefano Zampini 
229708122e43SStefano Zampini         if (B_neigs > nmax) {
2298fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2299fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2300fd14bc51SStefano Zampini           }
23019d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
230208122e43SStefano Zampini           B_neigs = nmax;
230308122e43SStefano Zampini         }
230408122e43SStefano Zampini 
23059552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
23069552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
230708122e43SStefano Zampini           PetscBLASInt B_neigs2;
230808122e43SStefano Zampini 
23099d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2310f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
23119d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
23129d54b7f4SStefano Zampini           } else {
23139d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
23149d54b7f4SStefano Zampini             B_IU = nmin_s;
23159d54b7f4SStefano Zampini           }
2316fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2317fd14bc51SStefano 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);
2318fd14bc51SStefano Zampini           }
23199ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
23201ae86dd6SStefano Zampini             PetscInt j,k;
232108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
23221ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
23231ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
23241ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
232508122e43SStefano Zampini               }
232608122e43SStefano Zampini             }
232708122e43SStefano Zampini           } else {
232808122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
232908122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
233008122e43SStefano Zampini           }
233108122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
233208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
23339d54b7f4SStefano 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));
233408122e43SStefano Zampini #else
23359d54b7f4SStefano 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));
233608122e43SStefano Zampini #endif
233708122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
233808122e43SStefano Zampini           B_neigs += B_neigs2;
233908122e43SStefano Zampini         }
234008122e43SStefano Zampini         if (B_ierr) {
23416c4ed002SBarry 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);
23426c4ed002SBarry 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);
23436c4ed002SBarry 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);
234408122e43SStefano Zampini         }
2345fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2346ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
234708122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
234808122e43SStefano Zampini             if (eigs[j] == 0.0) {
2349ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
235008122e43SStefano Zampini             } else {
23519d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2352ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
23539d54b7f4SStefano Zampini               } else {
23549d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
23559d54b7f4SStefano Zampini               }
2356fd14bc51SStefano Zampini             }
235708122e43SStefano Zampini           }
235808122e43SStefano Zampini         }
235908122e43SStefano Zampini       } else {
236008122e43SStefano Zampini           /* TODO */
236108122e43SStefano Zampini       }
2362aff50787SStefano Zampini     }
23636c3e6151SStefano Zampini     /* change the basis back to the original one */
23646c3e6151SStefano Zampini     if (sub_schurs->change) {
236572b8c272SStefano Zampini       Mat change,phi,phit;
23666c3e6151SStefano Zampini 
23676c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
23686c3e6151SStefano Zampini         PetscInt ii;
23696c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
23706c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
23716c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2372684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2373684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2374684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2375684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2376684229deSStefano Zampini #else
23776c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2378684229deSStefano Zampini #endif
23796c3e6151SStefano Zampini           }
23806c3e6151SStefano Zampini         }
23816c3e6151SStefano Zampini       }
238272b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
23836c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
238472b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
23856c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
23866c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
23876c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
23886c3e6151SStefano Zampini     }
23898bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
23908bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
23919162d606SStefano Zampini     if (B_neigs) {
23929162d606SStefano 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);
2393fd14bc51SStefano Zampini 
2394fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
23959552c7c7SStefano Zampini         PetscInt ii;
23969552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2397ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
23989552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2399ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2400ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2401ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2402ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2403ac47001eSStefano Zampini #else
2404ac47001eSStefano 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);
2405ac47001eSStefano Zampini #endif
24069552c7c7SStefano Zampini           }
24079552c7c7SStefano Zampini         }
2408fd14bc51SStefano Zampini       }
24099162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
24109162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
24119162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
24129162d606SStefano Zampini       cum++;
241308122e43SStefano Zampini     }
241408122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
241508122e43SStefano Zampini     /* shift for next computation */
241608122e43SStefano Zampini     cumarray += subset_size*subset_size;
241708122e43SStefano Zampini   }
2418fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2419fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2420fd14bc51SStefano Zampini   }
242108122e43SStefano Zampini 
242208122e43SStefano Zampini   if (mss) {
242308122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
242408122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2425f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2426f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2427f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
242808122e43SStefano Zampini   }
2429f6f667cfSStefano Zampini   if (allocated_S_St) {
2430f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2431f6f667cfSStefano Zampini   }
2432f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
243308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
243408122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
243508122e43SStefano Zampini #endif
243608122e43SStefano Zampini   if (pcbddc->dbg_flag) {
24371b968477SStefano Zampini     PetscInt maxneigs_r;
2438b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
24399b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
244008122e43SStefano Zampini   }
244108122e43SStefano Zampini   PetscFunctionReturn(0);
244208122e43SStefano Zampini }
2443b1b3d7a2SStefano Zampini 
2444674ae819SStefano Zampini #undef __FUNCT__
2445c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2446c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2447c8587f34SStefano Zampini {
24488629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2449c8587f34SStefano Zampini   PetscErrorCode ierr;
2450c8587f34SStefano Zampini 
2451c8587f34SStefano Zampini   PetscFunctionBegin;
2452f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
24535e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2454c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2455c8587f34SStefano Zampini 
2456684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
24570fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2458684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2459c8587f34SStefano Zampini 
24608629588bSStefano Zampini   /*
24618629588bSStefano Zampini      Setup local correction and local part of coarse basis.
24628629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
24638629588bSStefano Zampini   */
246447f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
24658629588bSStefano Zampini 
24668629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
24678629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
24688629588bSStefano Zampini 
24698629588bSStefano Zampini   /* free */
24708629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2471c8587f34SStefano Zampini   PetscFunctionReturn(0);
2472c8587f34SStefano Zampini }
2473c8587f34SStefano Zampini 
2474c8587f34SStefano Zampini #undef __FUNCT__
2475674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2476674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2477674ae819SStefano Zampini {
2478674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2479674ae819SStefano Zampini   PetscErrorCode ierr;
2480674ae819SStefano Zampini 
2481674ae819SStefano Zampini   PetscFunctionBegin;
2482674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
248330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2484674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2485785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2486674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2487f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2488f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2489785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
249063602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
249163602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2492674ae819SStefano Zampini   PetscFunctionReturn(0);
2493674ae819SStefano Zampini }
2494674ae819SStefano Zampini 
2495674ae819SStefano Zampini #undef __FUNCT__
2496674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2497674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2498674ae819SStefano Zampini {
2499674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
25004f1b2e48SStefano Zampini   PetscInt       i;
2501674ae819SStefano Zampini   PetscErrorCode ierr;
2502674ae819SStefano Zampini 
2503674ae819SStefano Zampini   PetscFunctionBegin;
2504a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2505b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2506674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
250716909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
25081dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2509674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2510669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2511fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2512a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2513674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
251471582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_FALSE;
25154f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
25164f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
25174f1b2e48SStefano Zampini   }
25184f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2519b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2520b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2521b334f244SStefano Zampini   }
2522674ae819SStefano Zampini   PetscFunctionReturn(0);
2523674ae819SStefano Zampini }
2524674ae819SStefano Zampini 
2525674ae819SStefano Zampini #undef __FUNCT__
2526674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2527674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2528674ae819SStefano Zampini {
2529674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2530674ae819SStefano Zampini   PetscErrorCode ierr;
2531674ae819SStefano Zampini 
2532674ae819SStefano Zampini   PetscFunctionBegin;
2533674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
253458da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2535ca92afb2SStefano Zampini     PetscScalar *array;
253606656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
253706656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
253858da7f69SStefano Zampini   }
2539674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2540674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
254115aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
254215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2543674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2544674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2545674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
254606656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2547674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2548674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
25498ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2550674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2551674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2552674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2553f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2554f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2555f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2556f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2557727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
25580e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2559f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
256070cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
256181d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
25620369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
25631dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
25644f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
25658b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2566ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2567ca92afb2SStefano Zampini     PetscInt i;
2568ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2569ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2570ca92afb2SStefano Zampini     }
2571ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2572ca92afb2SStefano Zampini   }
25734f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2574674ae819SStefano Zampini   PetscFunctionReturn(0);
2575674ae819SStefano Zampini }
2576674ae819SStefano Zampini 
2577674ae819SStefano Zampini #undef __FUNCT__
2578f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2579f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
25806bfb1811SStefano Zampini {
25816bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
25826bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
25836bfb1811SStefano Zampini   VecType        impVecType;
25844f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
25856bfb1811SStefano Zampini   PetscErrorCode ierr;
25866bfb1811SStefano Zampini 
25876bfb1811SStefano Zampini   PetscFunctionBegin;
25886c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2589e7b262bdSStefano Zampini   /* get sizes */
25904f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2591b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
25926bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2593e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2594e7b262bdSStefano Zampini   /* R nodes */
2595e7b262bdSStefano Zampini   old_size = -1;
2596e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2597e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2598e7b262bdSStefano Zampini   }
2599e7b262bdSStefano Zampini   if (n_R != old_size) {
2600e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2601e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
26026bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
26036bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
26046bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
26056bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2606e7b262bdSStefano Zampini   }
2607e7b262bdSStefano Zampini   /* local primal dofs */
2608e7b262bdSStefano Zampini   old_size = -1;
2609e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2610e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2611e7b262bdSStefano Zampini   }
2612e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2613e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
261483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2615e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
26166bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2617e7b262bdSStefano Zampini   }
2618e7b262bdSStefano Zampini   /* local explicit constraints */
2619e7b262bdSStefano Zampini   old_size = -1;
2620e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2621e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2622e7b262bdSStefano Zampini   }
2623e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2624e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
262583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
262683b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
262783b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
262883b7ccabSStefano Zampini   }
26296bfb1811SStefano Zampini   PetscFunctionReturn(0);
26306bfb1811SStefano Zampini }
26316bfb1811SStefano Zampini 
26326bfb1811SStefano Zampini #undef __FUNCT__
263347f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
263447f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
263588ebb749SStefano Zampini {
263625084f0cSStefano Zampini   PetscErrorCode  ierr;
263725084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
263888ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
263988ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2640d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
264125084f0cSStefano Zampini   /* submatrices of local problem */
264280677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
264306656605SStefano Zampini   /* submatrices of local coarse problem */
264406656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
264525084f0cSStefano Zampini   /* working matrices */
264606656605SStefano Zampini   Mat             C_CR;
264725084f0cSStefano Zampini   /* additional working stuff */
264806656605SStefano Zampini   PC              pc_R;
26494f1b2e48SStefano Zampini   Mat             F;
26505cbda25cSStefano Zampini   Vec             dummy_vec;
2651a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
265225084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
265306656605SStefano Zampini   PetscScalar     *work;
265406656605SStefano Zampini   PetscInt        *idx_V_B;
2655ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
265606656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2657ffd830a3SStefano Zampini 
265825084f0cSStefano Zampini   /* some shortcuts to scalars */
265906656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
266088ebb749SStefano Zampini 
266188ebb749SStefano Zampini   PetscFunctionBegin;
26629a962809SStefano 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");
2663ffd830a3SStefano Zampini 
2664ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2665b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
26664f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2667b371cd4fSStefano Zampini   n_B = pcis->n_B;
2668b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
266988ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
267088ebb749SStefano Zampini 
267188ebb749SStefano Zampini   /* vertices in boundary numbering */
2672785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
26730e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
26746c4ed002SBarry 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);
267588ebb749SStefano Zampini 
267606656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2677019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
267806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
267906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
268006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
268106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
268206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
268306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
268406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
268506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
268606656605SStefano Zampini 
268706656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
268806656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
268906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
269006656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
269106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2692ffd830a3SStefano Zampini   lda_rhs = n_R;
2693a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
269406656605SStefano Zampini   if (isLU || isILU || isCHOL) {
269506656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2696b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2697df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2698d62866d3SStefano Zampini     MatFactorType      type;
2699d62866d3SStefano Zampini 
2700df4d28bfSStefano Zampini     F = reuse_solver->F;
27016816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2702d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2703ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
270422db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
270506656605SStefano Zampini   } else {
270606656605SStefano Zampini     F = NULL;
270706656605SStefano Zampini   }
270806656605SStefano Zampini 
2709ffd830a3SStefano Zampini   /* allocate workspace */
2710ffd830a3SStefano Zampini   n = 0;
2711ffd830a3SStefano Zampini   if (n_constraints) {
2712ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2713ffd830a3SStefano Zampini   }
2714ffd830a3SStefano Zampini   if (n_vertices) {
2715ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2716ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2717ffd830a3SStefano Zampini   }
2718ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2719ffd830a3SStefano Zampini 
27205cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
27215cbda25cSStefano Zampini   dummy_vec = NULL;
27225cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
27235cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
27245cbda25cSStefano Zampini   }
27255cbda25cSStefano Zampini 
272688ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
272788ebb749SStefano Zampini   if (n_constraints) {
272872b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
272906656605SStefano Zampini     IS          is_aux;
273080677318SStefano Zampini     PetscScalar *array,*array2;
273106656605SStefano Zampini 
2732f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
273380677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
273488ebb749SStefano Zampini 
273525084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
273625084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
27378ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
273872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
273988ebb749SStefano Zampini 
274080677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
274180677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2742ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
274388ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
274406656605SStefano Zampini       const PetscScalar *row_cmat_values;
274506656605SStefano Zampini       const PetscInt    *row_cmat_indices;
274606656605SStefano Zampini       PetscInt          size_of_constraint,j;
274788ebb749SStefano Zampini 
274806656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
274906656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
2750ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
275106656605SStefano Zampini       }
275206656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
275306656605SStefano Zampini     }
2754ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
275506656605SStefano Zampini     if (F) {
275606656605SStefano Zampini       Mat B;
275706656605SStefano Zampini 
2758ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
2759a3df083aSStefano Zampini       if (need_benign_correction) {
2760df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2761a3df083aSStefano Zampini 
276272b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
276372b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2764a3df083aSStefano Zampini       }
276580677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
2766a3df083aSStefano Zampini       if (need_benign_correction) {
2767a3df083aSStefano Zampini         PetscScalar        *marr;
2768df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2769a3df083aSStefano Zampini 
2770a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
27715cbda25cSStefano Zampini         if (lda_rhs != n_R) {
27725cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
27735cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
27745cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
27755cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
27765cbda25cSStefano Zampini           }
27775cbda25cSStefano Zampini         } else {
2778a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
2779a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
27805cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2781a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2782a3df083aSStefano Zampini           }
27835cbda25cSStefano Zampini         }
2784a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
2785a3df083aSStefano Zampini       }
278606656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
278706656605SStefano Zampini     } else {
278880677318SStefano Zampini       PetscScalar *marr;
278980677318SStefano Zampini 
279080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
279106656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
2792ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2793ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
279406656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
279506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
279606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
279706656605SStefano Zampini       }
279880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
279906656605SStefano Zampini     }
280080677318SStefano Zampini     if (!pcbddc->switch_static) {
280180677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
280280677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
280380677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
280480677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
2805ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
280680677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
280780677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
280880677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
280980677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
281080677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
281180677318SStefano Zampini       }
281280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
281380677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
281472b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
281580677318SStefano Zampini     } else {
2816ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2817ffd830a3SStefano Zampini         IS dummy;
2818ffd830a3SStefano Zampini 
2819ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
282072b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
2821ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
2822ffd830a3SStefano Zampini       } else {
282380677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
282480677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
2825ffd830a3SStefano Zampini       }
282625084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
282780677318SStefano Zampini     }
282880677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
282980677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
283080677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
283106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
283206656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
283380677318SStefano Zampini     if (isCHOL) {
283480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
283580677318SStefano Zampini     } else {
283625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
283780677318SStefano Zampini     }
283880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
283906656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
284025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
284125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
284225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
284380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
284472b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
284572b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
284606656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
284706656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
2848f4ddd8eeSStefano Zampini   }
2849fc227af8SStefano Zampini 
2850fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
285188ebb749SStefano Zampini   if (n_vertices) {
285206656605SStefano Zampini     IS is_aux;
28533a50541eSStefano Zampini 
2854b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
28556816873aSStefano Zampini       IS tis;
28566816873aSStefano Zampini 
28576816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
28586816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
28596816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
28606816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
28616816873aSStefano Zampini     } else {
28623a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
28636816873aSStefano Zampini     }
28649577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
28659577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
286604708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
286725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
286888ebb749SStefano Zampini   }
286988ebb749SStefano Zampini 
287088ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
2871f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
287206656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
287306656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
287406656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
287506656605SStefano Zampini     }
2876f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
287706656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
287806656605SStefano Zampini       PetscScalar *marray;
287906656605SStefano Zampini 
288006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
288106656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
2882f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2883f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
2884f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
2885f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2886f4ddd8eeSStefano Zampini     }
2887f4ddd8eeSStefano Zampini   }
288806656605SStefano Zampini 
2889f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
289006656605SStefano Zampini     PetscScalar *marray;
289188ebb749SStefano Zampini 
289206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
28938eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
289406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
289588ebb749SStefano Zampini     }
28963301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
289706656605SStefano Zampini       n *= 2;
289888ebb749SStefano Zampini     }
289906656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
290006656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
290106656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
29028eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
290306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
290406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
290588ebb749SStefano Zampini     }
29063301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
290706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
29088eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
290906656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
291006656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
291188ebb749SStefano Zampini       }
291288ebb749SStefano Zampini     } else {
2913c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
2914c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
29151b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
2916c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
2917c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
2918c0553b1fSStefano Zampini       }
291988ebb749SStefano Zampini     }
292006656605SStefano Zampini   }
2921019a44ceSStefano Zampini 
292206656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
29234f1b2e48SStefano Zampini   p0_lidx_I = NULL;
29244f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
2925d12edf2fSStefano Zampini     const PetscInt *idxs;
2926d12edf2fSStefano Zampini 
2927d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
29284f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
29294f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
29304f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
29314f1b2e48SStefano Zampini     }
2932d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
2933d12edf2fSStefano Zampini   }
2934d16cbb6bSStefano Zampini 
293506656605SStefano Zampini   /* vertices */
293606656605SStefano Zampini   if (n_vertices) {
293716f15bc4SStefano Zampini 
2938af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
293904708bb6SStefano Zampini 
294016f15bc4SStefano Zampini     if (n_R) {
294114393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
294206656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
294316f15bc4SStefano Zampini       PetscScalar  *x,*y;
294404708bb6SStefano Zampini       PetscBool    isseqaij;
294506656605SStefano Zampini 
294621eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
294714393ed6SStefano Zampini       if (need_benign_correction) {
294814393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
294914393ed6SStefano Zampini         IS                     is_p0;
295014393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
295114393ed6SStefano Zampini 
295214393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
295314393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
295414393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2955af25d912SStefano 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);
295614393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
295714393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
295814393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
295914393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
296014393ed6SStefano Zampini       }
296114393ed6SStefano Zampini 
2962ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2963af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2964ffd830a3SStefano Zampini       } else {
2965ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2966ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2967ca92afb2SStefano Zampini         PetscInt       n;
2968ca92afb2SStefano Zampini         PetscBool      flg_row;
2969ffd830a3SStefano Zampini 
2970ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2971ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
29729d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2973ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2974ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2975ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2976ca92afb2SStefano Zampini           PetscInt j;
2977ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2978ffd830a3SStefano Zampini         }
2979ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2980ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2981ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2982ffd830a3SStefano Zampini       }
2983ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2984a3df083aSStefano Zampini       if (need_benign_correction) {
2985df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2986a3df083aSStefano Zampini         PetscScalar        *marr;
2987a3df083aSStefano Zampini 
2988a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
298914393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
299014393ed6SStefano Zampini 
299114393ed6SStefano Zampini                | 0 0  0 | (V)
299214393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
299314393ed6SStefano Zampini                | 0 0 -1 | (p0)
299414393ed6SStefano Zampini 
299514393ed6SStefano Zampini         */
2996df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
299714393ed6SStefano Zampini           const PetscScalar *vals;
299814393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
299914393ed6SStefano Zampini           PetscInt          n,j,nz;
300014393ed6SStefano Zampini 
3001df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3002df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
300314393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
300414393ed6SStefano Zampini           for (j=0;j<n;j++) {
300514393ed6SStefano Zampini             PetscScalar val = vals[j];
300614393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
300714393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
300814393ed6SStefano Zampini           }
300914393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3010df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
301114393ed6SStefano Zampini         }
301272b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
301372b8c272SStefano Zampini       }
301472b8c272SStefano Zampini       if (F) {
301514393ed6SStefano Zampini         /* need to correct the rhs */
301672b8c272SStefano Zampini         if (need_benign_correction) {
301772b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
301872b8c272SStefano Zampini           PetscScalar        *marr;
301972b8c272SStefano Zampini 
302072b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
30215cbda25cSStefano Zampini           if (lda_rhs != n_R) {
30225cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
30235cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30245cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
30255cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30265cbda25cSStefano Zampini             }
30275cbda25cSStefano Zampini           } else {
3028a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3029a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30305cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3031a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3032a3df083aSStefano Zampini             }
30335cbda25cSStefano Zampini           }
3034a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3035a3df083aSStefano Zampini         }
303606656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
303714393ed6SStefano Zampini         /* need to correct the solution */
3038a3df083aSStefano Zampini         if (need_benign_correction) {
3039df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3040a3df083aSStefano Zampini           PetscScalar        *marr;
3041a3df083aSStefano Zampini 
3042a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
30435cbda25cSStefano Zampini           if (lda_rhs != n_R) {
30445cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
30455cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30465cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
30475cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30485cbda25cSStefano Zampini             }
30495cbda25cSStefano Zampini           } else {
3050a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3051a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30525cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3053a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3054a3df083aSStefano Zampini             }
30555cbda25cSStefano Zampini           }
3056a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3057a3df083aSStefano Zampini         }
305806656605SStefano Zampini       } else {
305906656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
306006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3061ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3062ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
306306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
306406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
306506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
306606656605SStefano Zampini         }
306706656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
306806656605SStefano Zampini       }
306980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3070ffd830a3SStefano Zampini       /* S_VV and S_CV */
307106656605SStefano Zampini       if (n_constraints) {
307206656605SStefano Zampini         Mat B;
307380677318SStefano Zampini 
3074ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
307580677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3076ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3077ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
307880677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
307980677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
308080677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
308180677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
308280677318SStefano Zampini         }
3083ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
308480677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
308580677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3086ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
308780677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
308806656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3089ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3090ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
309106656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
309206656605SStefano Zampini       }
309304708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
309404708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3095511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
309604708bb6SStefano Zampini       }
3097ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3098ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3099ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3100ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3101ffd830a3SStefano Zampini       }
310206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
310314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
310414393ed6SStefano Zampini       if (need_benign_correction) {
3105df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
310614393ed6SStefano Zampini         PetscScalar      *marr,*sums;
310714393ed6SStefano Zampini 
310814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
310914393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3110df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
311114393ed6SStefano Zampini           const PetscScalar *vals;
311214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
311314393ed6SStefano Zampini           PetscInt          n,j,nz;
311414393ed6SStefano Zampini 
3115df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3116df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
311714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
311814393ed6SStefano Zampini             PetscInt k;
311914393ed6SStefano Zampini             sums[j] = 0.;
312014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
312114393ed6SStefano Zampini           }
312214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
312314393ed6SStefano Zampini           for (j=0;j<n;j++) {
312414393ed6SStefano Zampini             PetscScalar val = vals[j];
312514393ed6SStefano Zampini             PetscInt k;
312614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
312714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
312814393ed6SStefano Zampini             }
312914393ed6SStefano Zampini           }
313014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3131df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
313214393ed6SStefano Zampini         }
313314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
313414393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
313514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
313614393ed6SStefano Zampini       }
313780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
313806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
313906656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
314006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
314106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
314206656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
314306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
314406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3145d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3146019a44ceSStefano Zampini     } else {
3147d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3148d16cbb6bSStefano Zampini     }
314921eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3150d16cbb6bSStefano Zampini 
315106656605SStefano Zampini     /* coarse basis functions */
315206656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
315316f15bc4SStefano Zampini       PetscScalar *y;
315416f15bc4SStefano Zampini 
3155ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
315606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
315706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
315806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
315906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
316006656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
316106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
316206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
316306656605SStefano Zampini 
316406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
31654f1b2e48SStefano Zampini         PetscInt j;
31664f1b2e48SStefano Zampini 
316706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
316806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
316906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
317006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
317106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
31724f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
317306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
317406656605SStefano Zampini       }
317506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
317606656605SStefano Zampini     }
317704708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
317804708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
317906656605SStefano Zampini   }
31805cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
318106656605SStefano Zampini 
318206656605SStefano Zampini   if (n_constraints) {
318306656605SStefano Zampini     Mat B;
318406656605SStefano Zampini 
3185ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
318606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
318780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
318806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
318906656605SStefano Zampini     if (n_vertices) {
319080677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
319180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
319280677318SStefano Zampini       } else {
319380677318SStefano Zampini         Mat S_VCt;
319480677318SStefano Zampini 
3195ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3196ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
319772b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3198ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3199ffd830a3SStefano Zampini         }
320080677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
320180677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
320280677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
320380677318SStefano Zampini       }
320406656605SStefano Zampini     }
320506656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
320606656605SStefano Zampini     /* coarse basis functions */
320706656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
320806656605SStefano Zampini       PetscScalar *y;
320906656605SStefano Zampini 
3210ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
321106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
321206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
321306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
321406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
321506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
321606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
321706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
32184f1b2e48SStefano Zampini         PetscInt j;
32194f1b2e48SStefano Zampini 
322006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
322106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
322206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
322306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
322406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
32254f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
322606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
322706656605SStefano Zampini       }
322806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
322906656605SStefano Zampini     }
323006656605SStefano Zampini   }
323180677318SStefano Zampini   if (n_constraints) {
323280677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
323380677318SStefano Zampini   }
32344f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
323572b8c272SStefano Zampini 
323672b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
323772b8c272SStefano Zampini   if (pcbddc->benign_n) {
323872b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
323972b8c272SStefano Zampini     IS          is_dummy;
324072b8c272SStefano Zampini     PetscScalar *data;
324172b8c272SStefano Zampini     PetscInt    j;
324272b8c272SStefano Zampini 
324372b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
324472b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
324572b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
324672b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
324786c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
324872b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
324972b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
325072b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
325172b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
325272b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
325372b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
325472b8c272SStefano Zampini       }
325572b8c272SStefano Zampini     }
325672b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
325772b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
325872b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
325972b8c272SStefano Zampini   }
3260019a44ceSStefano Zampini 
326106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
32623301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3263ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3264ffd830a3SStefano Zampini     PetscScalar *marray;
326506656605SStefano Zampini 
326606656605SStefano Zampini     if (n_constraints) {
3267ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
326806656605SStefano Zampini 
3269af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
327006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3271ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
327216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
327306656605SStefano Zampini       if (n_vertices) {
3274ffd830a3SStefano Zampini         Mat S_VCT;
327506656605SStefano Zampini 
327606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3277ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
327816f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
327906656605SStefano Zampini       }
3280ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
32815b782168SStefano Zampini     } else {
32825b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
328306656605SStefano Zampini     }
328416f15bc4SStefano Zampini     if (n_vertices && n_R) {
3285ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3286ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3287ffd830a3SStefano Zampini       PetscInt       n;
3288ffd830a3SStefano Zampini       PetscBool      flg_row;
328906656605SStefano Zampini 
3290ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3291af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3292ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3293ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3294ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3295ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3296ffd830a3SStefano Zampini         PetscInt j;
3297ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3298ffd830a3SStefano Zampini       }
3299ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3300ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3301ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
330206656605SStefano Zampini     }
330306656605SStefano Zampini 
3304ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3305ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3306ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3307ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3308ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
330906656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
331006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
331106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
331206656605SStefano Zampini     }
3313ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
33145b782168SStefano Zampini     if (B_C) {
3315ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3316ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3317ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3318ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3319ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3320ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3321ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
332206656605SStefano Zampini       }
3323ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
33245b782168SStefano Zampini     }
332506656605SStefano Zampini     /* coarse basis functions */
332606656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
332706656605SStefano Zampini       PetscScalar *y;
332806656605SStefano Zampini 
3329ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
333006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
333106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
333206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
333406656605SStefano Zampini       if (i<n_vertices) {
333506656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
333606656605SStefano Zampini       }
333706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
333806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
333906656605SStefano Zampini 
334006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
334106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
334206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
334306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
334406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
334506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
334606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
334706656605SStefano Zampini       }
334806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
334906656605SStefano Zampini     }
3350ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3351ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
335206656605SStefano Zampini   }
3353d62866d3SStefano Zampini   /* free memory */
335488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
335506656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
335606656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
335706656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
335806656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3359d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3360d62866d3SStefano Zampini   if (n_vertices) {
3361d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3362d62866d3SStefano Zampini   }
3363d62866d3SStefano Zampini   if (n_constraints) {
3364d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3365d62866d3SStefano Zampini   }
336688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
336788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
336888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3369d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
337088ebb749SStefano Zampini     Mat         coarse_sub_mat;
337125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
337288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
337388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
337488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
33758bec7fa6SStefano Zampini     Mat         C_B,CPHI;
33768bec7fa6SStefano Zampini     IS          is_dummy;
33778bec7fa6SStefano Zampini     Vec         mones;
337888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
337988ebb749SStefano Zampini     PetscReal   real_value;
338088ebb749SStefano Zampini 
3381a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3382a3df083aSStefano Zampini       Mat A;
3383a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3384a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3385a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3386a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3387a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3388a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3389a3df083aSStefano Zampini     } else {
339088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
339188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
339288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
339388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3394a3df083aSStefano Zampini     }
339588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
339688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3397ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
339888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
339988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
340088ebb749SStefano Zampini     }
340188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
340288ebb749SStefano Zampini 
340325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
34043301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
340525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3406ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
340788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
340888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
340988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
341088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
341188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
341288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
341388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
341488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
341588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
341688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
341788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
341888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
341988ebb749SStefano Zampini     } else {
342088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
342188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
342288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
342388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
342488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
342588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
342688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
342788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
342888ebb749SStefano Zampini     }
342988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
343088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
343188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3432511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
34334f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3434fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3435d12edf2fSStefano Zampini       PetscScalar *data,*data2;
34364f1b2e48SStefano Zampini       PetscInt    j;
3437d12edf2fSStefano Zampini 
34384f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3439fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3440d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
344186c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3442d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3443d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
34444f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
34454f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3446d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
34474f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
34484f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
34494f1b2e48SStefano Zampini         }
3450d12edf2fSStefano Zampini       }
3451d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3452d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3453d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3454d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3455d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3456d12edf2fSStefano Zampini     }
3457d12edf2fSStefano Zampini #if 0
3458d12edf2fSStefano Zampini   {
3459d12edf2fSStefano Zampini     PetscViewer viewer;
3460d12edf2fSStefano Zampini     char filename[256];
3461ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3462d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3463d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3464ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3465ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3466ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3467d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
346872b8c272SStefano Zampini     if (save_change) {
346972b8c272SStefano Zampini       Mat phi_B;
347072b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
347172b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
347272b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
347372b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
347472b8c272SStefano Zampini     } else {
3475ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3476ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
347772b8c272SStefano Zampini     }
3478ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3479ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3480ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3481ffd830a3SStefano Zampini     }
3482ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3483ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3484ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3485ffd830a3SStefano Zampini     }
348672b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3487ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3488ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3489ffd830a3SStefano Zampini     }
3490d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3491d12edf2fSStefano Zampini   }
3492d12edf2fSStefano Zampini #endif
349381d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
34948bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
34951575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
349606656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
34978bec7fa6SStefano Zampini 
34988bec7fa6SStefano Zampini     /* check constraints */
3499a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3500a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
35014f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
35028bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3503a00504b5SStefano Zampini     } else {
3504a00504b5SStefano Zampini       PetscScalar *data;
3505a00504b5SStefano Zampini       Mat         tmat;
3506a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3507a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3508a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3509a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3510a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3511a00504b5SStefano Zampini     }
35128bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
35138bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
35148bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
35158bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3516bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3517ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3518bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3519bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3520bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3521bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3522bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
352388ebb749SStefano Zampini     }
35248bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
35258bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
35268bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
35278bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
352825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
352988ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
353088ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
353188ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
353288ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
353388ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
353488ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
353588ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
353688ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
353788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
353888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3539ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
354088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
354188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
354288ebb749SStefano Zampini     }
354388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
354488ebb749SStefano Zampini   }
35458629588bSStefano Zampini   /* get back data */
35468629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
354788ebb749SStefano Zampini   PetscFunctionReturn(0);
354888ebb749SStefano Zampini }
354988ebb749SStefano Zampini 
355088ebb749SStefano Zampini #undef __FUNCT__
3551d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3552d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3553aa0d41d4SStefano Zampini {
3554d65f70fdSStefano Zampini   Mat            *work_mat;
3555d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3556d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3557c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3558aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3559aa0d41d4SStefano Zampini 
3560aa0d41d4SStefano Zampini   PetscFunctionBegin;
3561d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3562d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3563d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3564d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3565aa0d41d4SStefano Zampini 
3566d65f70fdSStefano Zampini   if (!rsorted) {
3567906d46d4SStefano Zampini     const PetscInt *idxs;
3568906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3569aa0d41d4SStefano Zampini 
3570d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3571d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3572d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3573d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3574aa0d41d4SStefano Zampini     }
3575d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3576d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3577d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3578d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3579aa0d41d4SStefano Zampini     }
3580d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3581d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3582d65f70fdSStefano Zampini   } else {
3583d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3584d65f70fdSStefano Zampini     isrow_s = isrow;
3585aa0d41d4SStefano Zampini   }
3586906d46d4SStefano Zampini 
3587d65f70fdSStefano Zampini   if (!csorted) {
3588d65f70fdSStefano Zampini     if (isrow == iscol) {
3589d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3590d65f70fdSStefano Zampini       iscol_s = isrow_s;
3591d65f70fdSStefano Zampini     } else {
3592d65f70fdSStefano Zampini       const PetscInt *idxs;
3593d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3594906d46d4SStefano Zampini 
3595d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3596d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3597d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3598d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3599d65f70fdSStefano Zampini       }
3600d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3601d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3602d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3603d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3604d65f70fdSStefano Zampini       }
3605d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3606d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3607d65f70fdSStefano Zampini     }
3608d65f70fdSStefano Zampini   } else {
3609d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3610d65f70fdSStefano Zampini     iscol_s = iscol;
3611d65f70fdSStefano Zampini   }
3612d65f70fdSStefano Zampini 
3613d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3614d65f70fdSStefano Zampini 
3615d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3616906d46d4SStefano Zampini     Mat      new_mat;
3617d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3618906d46d4SStefano Zampini 
3619d65f70fdSStefano Zampini     if (!rsorted) {
3620d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3621d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3622d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3623d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3624906d46d4SStefano Zampini       }
3625d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3626d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3627d65f70fdSStefano Zampini     } else {
3628d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3629906d46d4SStefano Zampini     }
3630d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3631d65f70fdSStefano Zampini 
3632d65f70fdSStefano Zampini     if (!csorted) {
3633d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3634d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3635d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3636d65f70fdSStefano Zampini       } else {
3637d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3638d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3639d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3640d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3641d65f70fdSStefano Zampini         }
3642d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3643d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3644d65f70fdSStefano Zampini       }
3645d65f70fdSStefano Zampini     } else {
3646d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3647d65f70fdSStefano Zampini     }
3648d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3649d65f70fdSStefano Zampini 
3650d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3651d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3652d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3653d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3654d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3655d65f70fdSStefano Zampini   }
3656d65f70fdSStefano Zampini 
3657d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3658d65f70fdSStefano Zampini   *B = work_mat[0];
3659d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3660d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3661d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3662d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3663d65f70fdSStefano Zampini }
3664d65f70fdSStefano Zampini 
3665d65f70fdSStefano Zampini #undef __FUNCT__
36665e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
36675e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3668aa0d41d4SStefano Zampini {
3669aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
36705e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3671d65f70fdSStefano Zampini   Mat            new_mat;
36725e8657edSStefano Zampini   IS             is_local,is_global;
3673d65f70fdSStefano Zampini   PetscInt       local_size;
3674d65f70fdSStefano Zampini   PetscBool      isseqaij;
3675aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3676aa0d41d4SStefano Zampini 
3677aa0d41d4SStefano Zampini   PetscFunctionBegin;
3678aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
36795e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
36805e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3681b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3682aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3683d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3684aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3685906d46d4SStefano Zampini 
3686906d46d4SStefano Zampini   /* check */
3687906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3688906d46d4SStefano Zampini     Vec       x,x_change;
3689906d46d4SStefano Zampini     PetscReal error;
3690906d46d4SStefano Zampini 
36915e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3692906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
36935e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3694e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3695e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3696d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3697e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3698e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3699906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3700906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3701906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3702906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3703906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3704906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3705906d46d4SStefano Zampini   }
3706906d46d4SStefano Zampini 
370722d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
37089b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
370922d5777bSStefano Zampini   if (isseqaij) {
3710a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3711a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3712aa0d41d4SStefano Zampini   } else {
3713a00504b5SStefano Zampini     Mat work_mat;
37141cf9b237SStefano Zampini 
3715a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3716aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3717a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
37181d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3719aa0d41d4SStefano Zampini   }
37203301b35fSStefano Zampini   if (matis->A->symmetric_set) {
37213301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3722e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37233301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3724e496cd5dSStefano Zampini #endif
37253301b35fSStefano Zampini   }
3726d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3727aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3728aa0d41d4SStefano Zampini }
3729aa0d41d4SStefano Zampini 
3730aa0d41d4SStefano Zampini #undef __FUNCT__
3731a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
37328ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3733a64d13efSStefano Zampini {
3734a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3735a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3736d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
373753892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
37383a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
37393a50541eSStefano Zampini   PetscInt        vbs,bs;
37406816873aSStefano Zampini   PetscBT         bitmask=NULL;
3741a64d13efSStefano Zampini   PetscErrorCode  ierr;
3742a64d13efSStefano Zampini 
3743a64d13efSStefano Zampini   PetscFunctionBegin;
3744b23d619eSStefano Zampini   /*
3745b23d619eSStefano Zampini     No need to setup local scatters if
3746b23d619eSStefano Zampini       - primal space is unchanged
3747b23d619eSStefano Zampini         AND
3748b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
3749b23d619eSStefano Zampini         AND
3750b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
3751b23d619eSStefano Zampini   */
3752b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
3753f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
3754f4ddd8eeSStefano Zampini   }
3755f4ddd8eeSStefano Zampini   /* destroy old objects */
3756f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3757f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3758f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3759a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
3760b371cd4fSStefano Zampini   n_B = pcis->n_B;
3761b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
3762b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
37633a50541eSStefano Zampini 
3764a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
37656816873aSStefano Zampini 
376653892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
3767b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
3768854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
3769a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
3770a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
37710e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
3772a64d13efSStefano Zampini     }
3773a64d13efSStefano Zampini 
3774a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
37754641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
37766816873aSStefano Zampini         idx_R_local[n_R++] = i;
3777a64d13efSStefano Zampini       }
3778a64d13efSStefano Zampini     }
3779df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
3780df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
37816816873aSStefano Zampini 
3782df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3783df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
37846816873aSStefano Zampini   }
37853a50541eSStefano Zampini 
37863a50541eSStefano Zampini   /* Block code */
37873a50541eSStefano Zampini   vbs = 1;
37883a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
37893a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
37903a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
37913a50541eSStefano Zampini     PetscInt  *vary;
3792b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
3793785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
37943a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
3795d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
3796d3df7717SStefano 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 */
37970e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
3798d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
37993a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
38003a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
38013a50541eSStefano Zampini           break;
38023a50541eSStefano Zampini         }
38033a50541eSStefano Zampini       }
3804d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
3805d3df7717SStefano Zampini     } else {
3806d3df7717SStefano Zampini       /* Verify directly the R set */
3807d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
3808d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
3809d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
3810d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
3811d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
3812d3df7717SStefano Zampini             break;
3813d3df7717SStefano Zampini           }
3814d3df7717SStefano Zampini         }
3815d3df7717SStefano Zampini       }
3816d3df7717SStefano Zampini     }
38173a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
38183a50541eSStefano Zampini       vbs = bs;
38193a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
38203a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
38213a50541eSStefano Zampini       }
38223a50541eSStefano Zampini     }
38233a50541eSStefano Zampini   }
38243a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
3825b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
3826df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
382753892102SStefano Zampini 
3828df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3829df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
383053892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
3831df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
383253892102SStefano Zampini   } else {
38333a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
383453892102SStefano Zampini   }
3835a64d13efSStefano Zampini 
3836a64d13efSStefano Zampini   /* print some info if requested */
3837a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
3838a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3839a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38401575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3841a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
3842a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
38434f1b2e48SStefano 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);
3844a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3845a64d13efSStefano Zampini   }
3846a64d13efSStefano Zampini 
3847a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
3848b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
38496816873aSStefano Zampini     IS       is_aux1,is_aux2;
38506816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
38516816873aSStefano Zampini 
38523a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3853854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
3854854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
3855a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
38564641a718SStefano Zampini     for (i=0; i<n_D; i++) {
38574641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
38584641a718SStefano Zampini     }
3859a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3860a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
38614641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
38624641a718SStefano Zampini         aux_array1[j++] = i;
3863a64d13efSStefano Zampini       }
3864a64d13efSStefano Zampini     }
3865a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3866a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3867a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
38684641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
38694641a718SStefano Zampini         aux_array2[j++] = i;
3870a64d13efSStefano Zampini       }
3871a64d13efSStefano Zampini     }
3872a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3873a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
3874a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
3875a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3876a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
3877a64d13efSStefano Zampini 
38788eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3879785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
3880a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
38814641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
38824641a718SStefano Zampini           aux_array1[j++] = i;
3883a64d13efSStefano Zampini         }
3884a64d13efSStefano Zampini       }
3885a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3886a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
3887a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3888a64d13efSStefano Zampini     }
38894641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
38903a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3891d62866d3SStefano Zampini   } else {
3892df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
38936816873aSStefano Zampini     IS                 tis;
38946816873aSStefano Zampini     PetscInt           schur_size;
38956816873aSStefano Zampini 
3896df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
38976816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
3898df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
38996816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
39006816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
39016816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
39026816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
39036816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
3904d62866d3SStefano Zampini     }
3905d62866d3SStefano Zampini   }
3906a64d13efSStefano Zampini   PetscFunctionReturn(0);
3907a64d13efSStefano Zampini }
3908a64d13efSStefano Zampini 
3909304d26faSStefano Zampini 
3910304d26faSStefano Zampini #undef __FUNCT__
3911304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
3912684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
3913304d26faSStefano Zampini {
3914304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3915304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
3916304d26faSStefano Zampini   PC             pc_temp;
3917304d26faSStefano Zampini   Mat            A_RR;
3918f4ddd8eeSStefano Zampini   MatReuse       reuse;
3919304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
3920304d26faSStefano Zampini   PetscReal      value;
392104708bb6SStefano Zampini   PetscInt       n_D,n_R;
3922c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
3923304d26faSStefano Zampini   PetscErrorCode ierr;
3924e604994aSStefano Zampini   /* prefixes stuff */
3925312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
3926e604994aSStefano Zampini   size_t         len;
3927304d26faSStefano Zampini 
3928304d26faSStefano Zampini   PetscFunctionBegin;
3929304d26faSStefano Zampini 
3930e604994aSStefano Zampini   /* compute prefixes */
3931e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
3932e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
3933e604994aSStefano Zampini   if (!pcbddc->current_level) {
3934e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3935e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3936e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3937e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3938e604994aSStefano Zampini   } else {
3939e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3940312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3941e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3942e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3943312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3944312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
394534d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
394634d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3947e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3948e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3949e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3950e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3951e604994aSStefano Zampini   }
3952e604994aSStefano Zampini 
3953304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3954684f6988SStefano Zampini   if (dirichlet) {
3955d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3956450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
39579a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3958450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3959a3df083aSStefano Zampini         Mat    A_IIn;
3960a3df083aSStefano Zampini 
3961a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3962a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3963a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3964a3df083aSStefano Zampini       }
3965450f8f5eSStefano Zampini     }
39663301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
39673301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3968964fefecSStefano Zampini     }
3969ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3970964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3971304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3972304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3973304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3974304d26faSStefano Zampini       /* default */
3975304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3976e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
39779577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3978304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
39799577ea80SStefano Zampini       if (issbaij) {
39809577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
39819577ea80SStefano Zampini       } else {
3982304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
39839577ea80SStefano Zampini       }
3984304d26faSStefano Zampini       /* Allow user's customization */
3985304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3986304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3987304d26faSStefano Zampini     }
3988d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3989b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3990df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3991d62866d3SStefano Zampini 
3992df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3993d5574798SStefano Zampini     }
3994304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3995304d26faSStefano Zampini     if (!n_D) {
3996304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3997304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3998304d26faSStefano Zampini     }
3999304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4000304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4001304d26faSStefano Zampini     /* set ksp_D into pcis data */
4002304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4003304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4004304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4005684f6988SStefano Zampini   }
4006304d26faSStefano Zampini 
4007304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4008684f6988SStefano Zampini   A_RR = 0;
4009684f6988SStefano Zampini   if (neumann) {
4010d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
401104708bb6SStefano Zampini     PetscInt        ibs,mbs;
401204708bb6SStefano Zampini     PetscBool       issbaij;
401304708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4014f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
40158ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4016f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4017f4ddd8eeSStefano Zampini       PetscInt nn_R;
401881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4019f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4020f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4021f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4022f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4023f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4024f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4025f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4026727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4027f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4028f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4029f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4030f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4031f4ddd8eeSStefano Zampini         }
4032f4ddd8eeSStefano Zampini       }
4033f4ddd8eeSStefano Zampini       /* last check */
4034d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4035f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4036f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4037f4ddd8eeSStefano Zampini       }
4038f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4039f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4040f4ddd8eeSStefano Zampini     }
4041a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4042af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4043af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
404404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
404504708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
404604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
404704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
404804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4049af732b37SStefano Zampini       } else {
4050511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
40516816873aSStefano Zampini       }
405204708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
405304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
405404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
405504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
405604708bb6SStefano Zampini       } else {
4057511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
405804708bb6SStefano Zampini       }
405904708bb6SStefano Zampini     }
4060a00504b5SStefano Zampini     /* extract A_RR */
4061b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4062a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4063a00504b5SStefano Zampini 
4064a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
406516e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4066a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
406716e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
406816e386b8SStefano Zampini         } else {
4069a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4070a00504b5SStefano Zampini         }
4071a00504b5SStefano Zampini       } else {
4072a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4073a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4074a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4075a00504b5SStefano Zampini       }
4076a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4077f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
407816e386b8SStefano Zampini     }
40793301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
40803301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
40816816873aSStefano Zampini     }
4082f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4083304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4084304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4085304d26faSStefano Zampini       /* default */
4086304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4087e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4088304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
40899577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
40909577ea80SStefano Zampini       if (issbaij) {
40919577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
40929577ea80SStefano Zampini       } else {
4093304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
40949577ea80SStefano Zampini       }
4095304d26faSStefano Zampini       /* Allow user's customization */
4096304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4097304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4098304d26faSStefano Zampini     }
4099304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4100304d26faSStefano Zampini     if (!n_R) {
4101304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4102304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4103304d26faSStefano Zampini     }
41045cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4105df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4106b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4107df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4108d62866d3SStefano Zampini 
4109df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4110d62866d3SStefano Zampini     }
4111304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4112304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4113684f6988SStefano Zampini   }
4114304d26faSStefano Zampini 
4115684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4116684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41171575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4118684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4119684f6988SStefano Zampini   }
4120c7017625SStefano Zampini 
4121c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4122c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4123c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4124c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4125c7017625SStefano Zampini   }
4126c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4127c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4128c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4129c7017625SStefano Zampini   }
4130c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4131c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4132c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4133c7017625SStefano Zampini   }
4134c7017625SStefano Zampini 
4135c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4136c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4137684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
41380fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
41390fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
41400fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
41410fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
41420fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4143e604994aSStefano 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);
4144c7017625SStefano Zampini       if (check_corr[0]) {
4145c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4146c7017625SStefano Zampini       }
4147304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4148304d26faSStefano Zampini     }
4149684f6988SStefano Zampini     if (neumann) { /* Neumann */
41500fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
41510fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
41520fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
41530fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
41540fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4155e604994aSStefano 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);
4156c7017625SStefano Zampini       if (check_corr[1]) {
4157c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4158c7017625SStefano Zampini       }
4159304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4160304d26faSStefano Zampini     }
4161684f6988SStefano Zampini   }
41625cbda25cSStefano Zampini   /* free Neumann problem's matrix */
41635cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4164304d26faSStefano Zampini   PetscFunctionReturn(0);
4165304d26faSStefano Zampini }
4166304d26faSStefano Zampini 
4167304d26faSStefano Zampini #undef __FUNCT__
4168ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
416980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4170674ae819SStefano Zampini {
4171674ae819SStefano Zampini   PetscErrorCode  ierr;
4172674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4173be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4174b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4175674ae819SStefano Zampini 
4176674ae819SStefano Zampini   PetscFunctionBegin;
4177b334f244SStefano Zampini   if (!reuse_solver) {
417880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
417920c7b377SStefano Zampini   }
418080677318SStefano Zampini   if (!pcbddc->switch_static) {
418180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
418280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
418380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
418420c7b377SStefano Zampini     }
4185b334f244SStefano Zampini     if (!reuse_solver) {
418680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
418780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
418820c7b377SStefano Zampini     } else {
4189df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4190be83ff47SStefano Zampini 
4191df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4192df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
419320c7b377SStefano Zampini     }
4194be83ff47SStefano Zampini   } else {
419580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
419680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
419780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
419880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
419980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
420080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
420180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
420280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
420380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4204674ae819SStefano Zampini     }
4205674ae819SStefano Zampini   }
4206b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
420780677318SStefano Zampini     if (applytranspose) {
420880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
420980677318SStefano Zampini     } else {
421080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
421180677318SStefano Zampini     }
4212be83ff47SStefano Zampini   } else {
4213df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4214be83ff47SStefano Zampini 
4215be83ff47SStefano Zampini     if (applytranspose) {
4216df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4217be83ff47SStefano Zampini     } else {
4218df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4219be83ff47SStefano Zampini     }
4220be83ff47SStefano Zampini   }
422180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
422280677318SStefano Zampini   if (!pcbddc->switch_static) {
4223b334f244SStefano Zampini     if (!reuse_solver) {
422480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
422580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4226be83ff47SStefano Zampini     } else {
4227df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4228be83ff47SStefano Zampini 
4229df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4230df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4231be83ff47SStefano Zampini     }
423280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
423380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
423480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
423580677318SStefano Zampini     }
423680677318SStefano Zampini   } else {
423780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
423880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
423980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
424080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
424180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
424280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
424380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
424480677318SStefano Zampini     }
424580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
424680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
424780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
424880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4249674ae819SStefano Zampini   }
4250674ae819SStefano Zampini   PetscFunctionReturn(0);
4251674ae819SStefano Zampini }
4252674ae819SStefano Zampini 
4253dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4254674ae819SStefano Zampini #undef __FUNCT__
4255674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4256dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4257674ae819SStefano Zampini {
4258674ae819SStefano Zampini   PetscErrorCode ierr;
4259674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4260674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4261674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4262674ae819SStefano Zampini 
4263674ae819SStefano Zampini   PetscFunctionBegin;
4264dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
42654fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4266dc359a40SStefano Zampini     if (applytranspose) {
4267674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
42688eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4269dc359a40SStefano Zampini     } else {
4270674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4271674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
427215aaf578SStefano Zampini     }
42734fee134fSStefano Zampini   } else {
42744fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
42754fee134fSStefano Zampini   }
4276efc2fbd9SStefano Zampini 
4277efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
42784f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4279efc2fbd9SStefano Zampini     PetscScalar *array;
42804f1b2e48SStefano Zampini     PetscInt    j;
4281efc2fbd9SStefano Zampini 
4282efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
42834f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4284efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4285efc2fbd9SStefano Zampini   }
4286efc2fbd9SStefano Zampini 
428712edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
428812edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
428912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
429012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
429112edc857SStefano Zampini 
42929f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
429312edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
429451694757SStefano Zampini     Mat          coarse_mat;
4295964fefecSStefano Zampini     Vec          rhs,sol;
429651694757SStefano Zampini     MatNullSpace nullsp;
429727b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4298964fefecSStefano Zampini 
429927b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
430027b6a85dSStefano Zampini       PC        coarse_pc;
430127b6a85dSStefano Zampini 
430227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
430327b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
430427b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
430527b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
430627b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
430727b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
43083bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
430927b6a85dSStefano Zampini       }
431027b6a85dSStefano Zampini     }
4311964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4312964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
431351694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
431451694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
431551694757SStefano Zampini     if (nullsp) {
431651694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
431751694757SStefano Zampini     }
431812edc857SStefano Zampini     if (applytranspose) {
43199a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4320964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
43212701bc32SStefano Zampini     } else {
43221f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
43232701bc32SStefano Zampini         PC        coarse_pc;
43242701bc32SStefano Zampini 
43252701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
43262701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
43273e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
43282701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
432912edc857SStefano Zampini       } else {
4330964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
433112edc857SStefano Zampini       }
43322701bc32SStefano Zampini     }
43331d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
433427b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
433527b6a85dSStefano Zampini       PC        coarse_pc;
433627b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
433727b6a85dSStefano Zampini 
433827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
433927b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
434027b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
43413bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
434227b6a85dSStefano Zampini     }
434351694757SStefano Zampini     if (nullsp) {
434451694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
434551694757SStefano Zampini     }
434612edc857SStefano Zampini   }
4347674ae819SStefano Zampini 
4348674ae819SStefano Zampini   /* Local solution on R nodes */
43494fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
435080677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
43519f00e9b4SStefano Zampini   }
43529f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
43539f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
435412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4355674ae819SStefano Zampini 
43564fee134fSStefano Zampini   /* Sum contributions from the two levels */
43574fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4358dc359a40SStefano Zampini     if (applytranspose) {
4359dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4360dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4361dc359a40SStefano Zampini     } else {
4362674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
43638eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4364dc359a40SStefano Zampini     }
4365efc2fbd9SStefano Zampini     /* store p0 */
43664f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4367efc2fbd9SStefano Zampini       PetscScalar *array;
43684f1b2e48SStefano Zampini       PetscInt    j;
4369efc2fbd9SStefano Zampini 
4370efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
43714f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4372efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4373efc2fbd9SStefano Zampini     }
43744fee134fSStefano Zampini   } else { /* expand the coarse solution */
43754fee134fSStefano Zampini     if (applytranspose) {
43764fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
43774fee134fSStefano Zampini     } else {
43784fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
43794fee134fSStefano Zampini     }
43804fee134fSStefano Zampini   }
4381674ae819SStefano Zampini   PetscFunctionReturn(0);
4382674ae819SStefano Zampini }
4383674ae819SStefano Zampini 
4384674ae819SStefano Zampini #undef __FUNCT__
4385674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
438612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4387674ae819SStefano Zampini {
4388674ae819SStefano Zampini   PetscErrorCode ierr;
4389674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
439058da7f69SStefano Zampini   PetscScalar    *array;
439112edc857SStefano Zampini   Vec            from,to;
4392674ae819SStefano Zampini 
4393674ae819SStefano Zampini   PetscFunctionBegin;
439412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
439512edc857SStefano Zampini     from = pcbddc->coarse_vec;
439612edc857SStefano Zampini     to = pcbddc->vec1_P;
439712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
439812edc857SStefano Zampini       Vec tvec;
439958da7f69SStefano Zampini 
440058da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
440158da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
440212edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
440358da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
440458da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
440558da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
440612edc857SStefano Zampini     }
440712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
440812edc857SStefano Zampini     from = pcbddc->vec1_P;
440912edc857SStefano Zampini     to = pcbddc->coarse_vec;
441012edc857SStefano Zampini   }
441112edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4412674ae819SStefano Zampini   PetscFunctionReturn(0);
4413674ae819SStefano Zampini }
4414674ae819SStefano Zampini 
4415674ae819SStefano Zampini #undef __FUNCT__
4416674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
441712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4418674ae819SStefano Zampini {
4419674ae819SStefano Zampini   PetscErrorCode ierr;
4420674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
442158da7f69SStefano Zampini   PetscScalar    *array;
442212edc857SStefano Zampini   Vec            from,to;
4423674ae819SStefano Zampini 
4424674ae819SStefano Zampini   PetscFunctionBegin;
442512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
442612edc857SStefano Zampini     from = pcbddc->coarse_vec;
442712edc857SStefano Zampini     to = pcbddc->vec1_P;
442812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
442912edc857SStefano Zampini     from = pcbddc->vec1_P;
443012edc857SStefano Zampini     to = pcbddc->coarse_vec;
443112edc857SStefano Zampini   }
443212edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
443312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
443412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
443512edc857SStefano Zampini       Vec tvec;
443658da7f69SStefano Zampini 
443712edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
443858da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
443958da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
444058da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
444158da7f69SStefano Zampini     }
444258da7f69SStefano Zampini   } else {
444358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
444458da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
444512edc857SStefano Zampini     }
444612edc857SStefano Zampini   }
4447674ae819SStefano Zampini   PetscFunctionReturn(0);
4448674ae819SStefano Zampini }
4449674ae819SStefano Zampini 
4450984c4197SStefano Zampini /* uncomment for testing purposes */
4451984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4452674ae819SStefano Zampini #undef __FUNCT__
4453674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4454674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4455674ae819SStefano Zampini {
4456674ae819SStefano Zampini   PetscErrorCode    ierr;
4457674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4458674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4459674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4460984c4197SStefano Zampini   /* one and zero */
4461984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4462984c4197SStefano Zampini   /* space to store constraints and their local indices */
44639162d606SStefano Zampini   PetscScalar       *constraints_data;
44649162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
44659162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
44669162d606SStefano Zampini   PetscInt          *constraints_n;
4467984c4197SStefano Zampini   /* iterators */
4468b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4469984c4197SStefano Zampini   /* BLAS integers */
4470e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4471e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4472c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4473727cdba6SStefano Zampini   /* reuse */
44740e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
44750e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4476984c4197SStefano Zampini   /* change of basis */
4477b3d85658SStefano Zampini   PetscBool         qr_needed;
44789162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4479984c4197SStefano Zampini   /* auxiliary stuff */
448064efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
44818a0068c3SStefano Zampini   PetscInt          ncc;
4482984c4197SStefano Zampini   /* some quantities */
448345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4484a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4485984c4197SStefano Zampini 
4486674ae819SStefano Zampini   PetscFunctionBegin;
44878e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
44888e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
44898e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
449016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4491088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4492088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
44930e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
44940e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
44950e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
44960e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
44970e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4498088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4499cf5a6209SStefano Zampini 
4500cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
45019162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4502cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4503cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4504cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4505cf5a6209SStefano Zampini     PetscScalar  *array;
4506cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4507cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4508674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4509b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4510674ae819SStefano Zampini     PetscScalar  *work;
4511674ae819SStefano Zampini     PetscReal    *singular_vals;
4512674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4513674ae819SStefano Zampini     PetscReal    *rwork;
4514674ae819SStefano Zampini #endif
4515674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4516674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4517674ae819SStefano Zampini #else
4518964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4519964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4520674ae819SStefano Zampini #endif
4521674ae819SStefano Zampini 
4522674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4523d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4524e4d548c7SStefano Zampini     /* print some info */
45251f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4526e4d548c7SStefano Zampini       PetscInt nv;
4527e4d548c7SStefano Zampini 
4528c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4529e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4530e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4531e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4532e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4533e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4534e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4535e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4536e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4537e4d548c7SStefano Zampini     }
4538e4d548c7SStefano Zampini 
4539d06fc5fdSStefano Zampini     /* free unneeded index sets */
4540d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4541d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4542674ae819SStefano Zampini     }
4543d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4544d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4545d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4546d06fc5fdSStefano Zampini       }
4547d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4548d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4549d06fc5fdSStefano Zampini     }
4550d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4551d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4552d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4553d06fc5fdSStefano Zampini       }
4554d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4555d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4556d06fc5fdSStefano Zampini     }
455770022509SStefano Zampini 
4558674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4559674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4560674ae819SStefano Zampini     if (nearnullsp) {
4561674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4562f4ddd8eeSStefano Zampini       /* remove any stored info */
4563f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4564f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4565f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4566f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4567f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4568473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4569f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4570f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4571f4ddd8eeSStefano Zampini       }
4572984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4573984c4197SStefano Zampini       nnsp_size = 0;
4574674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4575674ae819SStefano Zampini     }
4576984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4577984c4197SStefano Zampini     max_constraints = nnsp_size;
4578984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4579984c4197SStefano Zampini 
4580674ae819SStefano Zampini     /*
4581674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
45829162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
45839162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
45849162d606SStefano Zampini          There can be multiple constraints per connected component
4585674ae819SStefano Zampini                                                                                                                                                            */
4586674ae819SStefano Zampini     n_vertices = 0;
4587674ae819SStefano Zampini     if (ISForVertices) {
4588674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4589674ae819SStefano Zampini     }
45909162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
45919162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
45929162d606SStefano Zampini 
45939162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
45949162d606SStefano Zampini     total_counts *= max_constraints;
4595674ae819SStefano Zampini     total_counts += n_vertices;
45964641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
45979162d606SStefano Zampini 
4598674ae819SStefano Zampini     total_counts = 0;
4599674ae819SStefano Zampini     max_size_of_constraint = 0;
4600674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
46019162d606SStefano Zampini       IS used_is;
4602674ae819SStefano Zampini       if (i<n_ISForEdges) {
46039162d606SStefano Zampini         used_is = ISForEdges[i];
4604674ae819SStefano Zampini       } else {
46059162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4606674ae819SStefano Zampini       }
46079162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4608674ae819SStefano Zampini       total_counts += j;
4609674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4610674ae819SStefano Zampini     }
46119162d606SStefano 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);
46129162d606SStefano Zampini 
4613984c4197SStefano Zampini     /* get local part of global near null space vectors */
4614785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4615984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4616984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4617e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4618e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4619984c4197SStefano Zampini     }
4620674ae819SStefano Zampini 
4621242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4622242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4623a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4624242a89d7SStefano Zampini 
4625984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4626a773dcb8SStefano Zampini     if (!skip_lapack) {
4627674ae819SStefano Zampini       PetscScalar temp_work;
4628911cabfeSStefano Zampini 
4629674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4630984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4631785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4632785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4633785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4634674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4635785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4636674ae819SStefano Zampini #endif
4637674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4638c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4639c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4640674ae819SStefano Zampini       lwork = -1;
4641674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4642674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4643c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4644674ae819SStefano Zampini #else
4645c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4646674ae819SStefano Zampini #endif
4647674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4648984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4649674ae819SStefano Zampini #else /* on missing GESVD */
4650674ae819SStefano Zampini       /* SVD */
4651674ae819SStefano Zampini       PetscInt max_n,min_n;
4652674ae819SStefano Zampini       max_n = max_size_of_constraint;
4653984c4197SStefano Zampini       min_n = max_constraints;
4654984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4655674ae819SStefano Zampini         min_n = max_size_of_constraint;
4656984c4197SStefano Zampini         max_n = max_constraints;
4657674ae819SStefano Zampini       }
4658785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4659674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4660785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4661674ae819SStefano Zampini #endif
4662674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4663674ae819SStefano Zampini       lwork = -1;
4664e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4665e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4666b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4667674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4668674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
46699162d606SStefano 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));
4670674ae819SStefano Zampini #else
46719162d606SStefano 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));
4672674ae819SStefano Zampini #endif
4673674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4674984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4675984c4197SStefano Zampini #endif /* on missing GESVD */
4676674ae819SStefano Zampini       /* Allocate optimal workspace */
4677674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4678854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4679674ae819SStefano Zampini     }
4680674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4681674ae819SStefano Zampini     total_counts = 0;
46829162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
46839162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4684674ae819SStefano Zampini     /* vertices */
46859162d606SStefano Zampini     if (n_vertices) {
4686674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
46879162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4688674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
46899162d606SStefano Zampini         constraints_n[total_counts] = 1;
46909162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
46919162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
46929162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4693674ae819SStefano Zampini         total_counts++;
4694674ae819SStefano Zampini       }
4695674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4696674ae819SStefano Zampini       n_vertices = total_counts;
4697674ae819SStefano Zampini     }
4698984c4197SStefano Zampini 
4699674ae819SStefano Zampini     /* edges and faces */
47009162d606SStefano Zampini     total_counts_cc = total_counts;
4701911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
47029162d606SStefano Zampini       IS        used_is;
47039162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
47049162d606SStefano Zampini 
4705911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
47069162d606SStefano Zampini         used_is = ISForEdges[ncc];
4707984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4708674ae819SStefano Zampini       } else {
47099162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4710984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4711674ae819SStefano Zampini       }
4712674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
47139162d606SStefano Zampini 
47149162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
47159162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4716984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4717984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4718674ae819SStefano Zampini       if (nnsp_has_cnst) {
47195b08dc53SStefano Zampini         PetscScalar quad_value;
47209162d606SStefano Zampini 
47219162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
47229162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
47239162d606SStefano Zampini 
4724a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4725674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4726a773dcb8SStefano Zampini         } else {
4727a773dcb8SStefano Zampini           quad_value = 1.0;
4728a773dcb8SStefano Zampini         }
4729674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
47309162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4731674ae819SStefano Zampini         }
47329162d606SStefano Zampini         temp_constraints++;
4733674ae819SStefano Zampini         total_counts++;
4734674ae819SStefano Zampini       }
4735674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4736984c4197SStefano Zampini         PetscReal real_value;
47379162d606SStefano Zampini         PetscScalar *ptr_to_data;
47389162d606SStefano Zampini 
4739984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
47409162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4741674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
47429162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4743674ae819SStefano Zampini         }
4744984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
4745984c4197SStefano Zampini         /* check if array is null on the connected component */
4746e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
47479162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
47485b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
4749674ae819SStefano Zampini           temp_constraints++;
4750674ae819SStefano Zampini           total_counts++;
47519162d606SStefano Zampini           if (!idxs_copied) {
47529162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
47539162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
4754674ae819SStefano Zampini           }
4755674ae819SStefano Zampini         }
47569162d606SStefano Zampini       }
47579162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
475845a1bb75SStefano Zampini       valid_constraints = temp_constraints;
4759eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
4760a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
47619162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
47629162d606SStefano Zampini 
47639162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4764a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
47659162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
4766a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
47679162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
4768a773dcb8SStefano Zampini         } else { /* perform SVD */
4769984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
47709162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4771674ae819SStefano Zampini 
4772674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4773984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
4774984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
4775984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
4776984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
4777984c4197SStefano Zampini                 from that computed using LAPACKgesvd
4778984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
4779984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
4780984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
4781674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
4782e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4783984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4784674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
4785674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
47869162d606SStefano 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));
4787674ae819SStefano Zampini             }
4788674ae819SStefano Zampini           }
4789e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
4790e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4791e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
4792674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4793c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
4794674ae819SStefano Zampini #else
4795c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
4796674ae819SStefano Zampini #endif
4797674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4798984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
4799984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
4800674ae819SStefano Zampini           j = 0;
4801984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
4802674ae819SStefano Zampini           total_counts = total_counts-j;
480345a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
4804e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
4805c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
4806c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4807c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
4808c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4809c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
4810c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4811674ae819SStefano Zampini           if (j<temp_constraints) {
4812984c4197SStefano Zampini             PetscInt ii;
4813984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
4814674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
48159162d606SStefano 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));
4816674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4817984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
4818674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
48199162d606SStefano 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];
4820674ae819SStefano Zampini               }
4821674ae819SStefano Zampini             }
4822674ae819SStefano Zampini           }
4823674ae819SStefano Zampini #else  /* on missing GESVD */
4824e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
4825e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4826b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4827674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4828674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
48299162d606SStefano 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));
4830674ae819SStefano Zampini #else
48319162d606SStefano 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));
4832674ae819SStefano Zampini #endif
4833984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
4834674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4835984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
4836e310c8b4SStefano Zampini           k = temp_constraints;
4837e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
4838674ae819SStefano Zampini           j = 0;
4839e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
484045a1bb75SStefano Zampini           valid_constraints = k-j;
4841911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
4842984c4197SStefano Zampini #endif /* on missing GESVD */
4843674ae819SStefano Zampini         }
4844a773dcb8SStefano Zampini       }
48459162d606SStefano Zampini       /* update pointers information */
48469162d606SStefano Zampini       if (valid_constraints) {
48479162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
48489162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
48499162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
48509162d606SStefano Zampini         /* set change_of_basis flag */
485145a1bb75SStefano Zampini         if (boolforchange) {
4852b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
48539162d606SStefano Zampini         }
4854b3d85658SStefano Zampini         total_counts_cc++;
485545a1bb75SStefano Zampini       }
485645a1bb75SStefano Zampini     }
4857984c4197SStefano Zampini     /* free workspace */
48588f1c130eSStefano Zampini     if (!skip_lapack) {
4859984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
4860984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4861984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
4862984c4197SStefano Zampini #endif
4863984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
4864984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4865984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
4866984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
4867984c4197SStefano Zampini #endif
4868984c4197SStefano Zampini     }
4869984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4870984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
4871984c4197SStefano Zampini     }
4872984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
4873cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
4874cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
4875cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4876cf5a6209SStefano Zampini     }
4877cf5a6209SStefano Zampini     if (n_ISForFaces) {
4878cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4879cf5a6209SStefano Zampini     }
4880cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
4881cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4882cf5a6209SStefano Zampini     }
4883cf5a6209SStefano Zampini     if (n_ISForEdges) {
4884cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4885cf5a6209SStefano Zampini     }
4886cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
488708122e43SStefano Zampini   } else {
488808122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4889984c4197SStefano Zampini 
489008122e43SStefano Zampini     total_counts = 0;
489108122e43SStefano Zampini     n_vertices = 0;
4892d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
4893d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
489408122e43SStefano Zampini     }
489508122e43SStefano Zampini     max_constraints = 0;
48969162d606SStefano Zampini     total_counts_cc = 0;
489708122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
489808122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
48999162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
490008122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
490108122e43SStefano Zampini     }
49029162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
49039162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
49049162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
49059162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
490674d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
49079162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
49089162d606SStefano Zampini     total_counts_cc = 0;
49099162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
49109162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
49119162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
491208122e43SStefano Zampini       }
491308122e43SStefano Zampini     }
49149162d606SStefano Zampini #if 0
49159162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
49169162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
49179162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
49189162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
49199162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
49209162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
49219162d606SStefano Zampini       }
49229162d606SStefano Zampini       printf("\n");
49239162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
49249162d606SStefano Zampini     }
49251b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
49268bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
49271b968477SStefano Zampini     }
49281b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
49298bec7fa6SStefano 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]);
49301b968477SStefano Zampini     }
493108122e43SStefano Zampini #endif
493208122e43SStefano Zampini 
49338bec7fa6SStefano Zampini     max_size_of_constraint = 0;
49349162d606SStefano 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]);
49359162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
493608122e43SStefano Zampini     /* Change of basis */
4937b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
493808122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
493908122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
494008122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4941b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
494208122e43SStefano Zampini         }
494308122e43SStefano Zampini       }
494408122e43SStefano Zampini     }
494508122e43SStefano Zampini   }
4946984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
49474f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
494808122e43SStefano Zampini 
49499162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
49509162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
49516c4ed002SBarry 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);
4952674ae819SStefano Zampini 
4953674ae819SStefano Zampini   /* Create constraint matrix */
4954674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
495516f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4956984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4957984c4197SStefano Zampini 
4958984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4959a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4960a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
496174d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4962984c4197SStefano Zampini   total_primal_vertices=0;
4963b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
49649162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
49659162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
496672b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
49679162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4968b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
496964efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
49709162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
49719162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4972a717540cSStefano Zampini       }
4973b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
497491af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4975a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4976a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4977a717540cSStefano Zampini       }
4978fa434743SStefano Zampini     } else {
4979b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4980fa434743SStefano Zampini     }
4981a717540cSStefano Zampini   }
4982b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4983b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4984674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
498570022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4986b3d85658SStefano Zampini 
49874f1b2e48SStefano 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);
49880e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
49890e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4990984c4197SStefano Zampini 
4991984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
499274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4993785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4994984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
499574d5cdf7SStefano Zampini 
4996984c4197SStefano Zampini   j = total_primal_vertices;
499774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4998b3d85658SStefano Zampini   cum = total_primal_vertices;
49999162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
50004641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5001b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5002b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5003b3d85658SStefano Zampini       cum++;
50049162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
500574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
500674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
500774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
500874d5cdf7SStefano Zampini       }
50099162d606SStefano Zampini       j += constraints_n[i];
5010674ae819SStefano Zampini     }
5011674ae819SStefano Zampini   }
5012674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5013674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5014088faed8SStefano Zampini 
5015674ae819SStefano Zampini   /* set values in constraint matrix */
5016984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
50170e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5018674ae819SStefano Zampini   }
5019984c4197SStefano Zampini   total_counts = total_primal_vertices;
50209162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
50214641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
50229162d606SStefano Zampini       PetscInt *cols;
50239162d606SStefano Zampini 
50249162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
50259162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
50269162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
50279162d606SStefano Zampini         PetscInt    row = total_counts+k;
50289162d606SStefano Zampini         PetscScalar *vals;
50299162d606SStefano Zampini 
50309162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
50319162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
50329162d606SStefano Zampini       }
50339162d606SStefano Zampini       total_counts += constraints_n[i];
5034674ae819SStefano Zampini     }
5035674ae819SStefano Zampini   }
5036674ae819SStefano Zampini   /* assembling */
5037674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5038674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5039088faed8SStefano Zampini 
5040984c4197SStefano Zampini   /*
50416a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5042984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5043f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5044984c4197SStefano Zampini   */
5045674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5046674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5047026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5048984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5049984c4197SStefano Zampini     /* working stuff for GEQRF */
505081d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5051984c4197SStefano Zampini     PetscBLASInt lqr_work;
5052984c4197SStefano Zampini     /* working stuff for UNGQR */
5053984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5054984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5055984c4197SStefano Zampini     /* working stuff for TRTRS */
5056984c4197SStefano Zampini     PetscScalar  *trs_rhs;
50573f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5058984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5059984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5060984c4197SStefano Zampini     PetscScalar  *start_vals;
5061984c4197SStefano Zampini     /* working stuff for values insertion */
50624641a718SStefano Zampini     PetscBT      is_primal;
506364efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5064906d46d4SStefano Zampini     /* matrix sizes */
5065906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5066906d46d4SStefano Zampini     /* temporary change of basis */
5067906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5068cf5a6209SStefano Zampini     /* extra space for debugging */
5069cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5070984c4197SStefano Zampini 
5071906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5072906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
507316f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5074bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5075906d46d4SStefano Zampini     /* nonzeros for local mat */
5076bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
50771dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5078bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
50791dd7afcfSStefano Zampini     } else {
50801dd7afcfSStefano Zampini       const PetscInt *ii;
50811dd7afcfSStefano Zampini       PetscInt       n;
50821dd7afcfSStefano Zampini       PetscBool      flg_row;
50831dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
50841dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
50851dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
50861dd7afcfSStefano Zampini     }
50879162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5088a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
50899162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5090a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
50919162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5092a717540cSStefano Zampini         } else {
50939162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
50949162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5095a717540cSStefano Zampini         }
5096a717540cSStefano Zampini       }
5097a717540cSStefano Zampini     }
5098906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5099bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
51001dd7afcfSStefano Zampini     /* Set interior change in the matrix */
51011dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5102bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5103906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5104a717540cSStefano Zampini       }
51051dd7afcfSStefano Zampini     } else {
51061dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
51071dd7afcfSStefano Zampini       PetscScalar    *aa;
51081dd7afcfSStefano Zampini       PetscInt       n;
51091dd7afcfSStefano Zampini       PetscBool      flg_row;
51101dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
51111dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
51121dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
51131dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
51141dd7afcfSStefano Zampini       }
51151dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
51161dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
51171dd7afcfSStefano Zampini     }
5118a717540cSStefano Zampini 
5119a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5120a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5121a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5122a717540cSStefano Zampini     }
5123a717540cSStefano Zampini 
5124a717540cSStefano Zampini 
5125a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5126a717540cSStefano Zampini     /*
5127a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5128a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5129a717540cSStefano Zampini 
5130a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5131a717540cSStefano Zampini 
5132a6b551f4SStefano 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)
5133a6b551f4SStefano Zampini 
5134a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5135a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5136a717540cSStefano Zampini             |              ...                        |
5137a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5138a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5139a717540cSStefano Zampini 
5140a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5141a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5142a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5143a6b551f4SStefano Zampini 
5144a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5145a717540cSStefano Zampini     */
5146a717540cSStefano Zampini     if (qr_needed) {
5147984c4197SStefano Zampini       /* space to store Q */
5148854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
5149984c4197SStefano Zampini       /* first we issue queries for optimal work */
51503f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
51513f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
51523f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5153984c4197SStefano Zampini       lqr_work = -1;
51543f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5155984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5156984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5157785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5158984c4197SStefano Zampini       lgqr_work = -1;
51593f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
51603f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
51613f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
51623f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
51633f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
51643f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5165984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5166984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5167785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5168984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
5169785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5170984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5171785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5172a717540cSStefano Zampini       /* allocating workspace for check */
5173a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5174cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5175a717540cSStefano Zampini       }
5176a717540cSStefano Zampini     }
5177984c4197SStefano Zampini     /* array to store whether a node is primal or not */
51784641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5179473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
51800e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
51816c4ed002SBarry 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);
518239e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
518339e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
518439e2fb2aSStefano Zampini     }
518539e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5186984c4197SStefano Zampini 
5187a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
51889162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
51899162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
51904641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5191984c4197SStefano Zampini         /* get constraint info */
51929162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5193984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5194984c4197SStefano Zampini 
5195984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
51969162d606SStefano 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);
5197674ae819SStefano Zampini         }
5198984c4197SStefano Zampini 
5199fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5200a717540cSStefano Zampini 
5201a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5202a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
52039162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5204a717540cSStefano Zampini           }
5205984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
52069162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5207984c4197SStefano Zampini 
5208984c4197SStefano Zampini           /* compute QR decomposition of constraints */
52093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52103f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52113f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5212674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52133f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5214984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5215674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5216984c4197SStefano Zampini 
5217984c4197SStefano Zampini           /* explictly compute R^-T */
5218984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5219984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
52203f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52213f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
52223f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
52233f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5224984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52253f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5226984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5227984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5228984c4197SStefano Zampini 
5229a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
52303f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52313f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
52323f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
52333f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5234984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52353f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5236984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5237984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5238984c4197SStefano Zampini 
5239984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5240984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5241984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
52423f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52433f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52443f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
52453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
52463f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
52473f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5248984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52499162d606SStefano 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));
5250984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
52519162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5252984c4197SStefano Zampini 
5253984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
52549162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5255984c4197SStefano Zampini           /* insert cols for primal dofs */
5256984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5257984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
52589162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5259906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5260984c4197SStefano Zampini           }
5261984c4197SStefano Zampini           /* insert cols for dual dofs */
5262984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
52639162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5264984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
52659162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5266906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5267984c4197SStefano Zampini               j++;
5268674ae819SStefano Zampini             }
5269674ae819SStefano Zampini           }
5270984c4197SStefano Zampini 
5271984c4197SStefano Zampini           /* check change of basis */
5272984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5273984c4197SStefano Zampini             PetscInt   ii,jj;
5274984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5275c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5276c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5277c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5278c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5279c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5280c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5281984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5282cf5a6209SStefano 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));
5283984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5284984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5285984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5286cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5287cf5a6209SStefano 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;
5288674ae819SStefano Zampini               }
5289674ae819SStefano Zampini             }
5290984c4197SStefano Zampini             if (!valid_qr) {
529122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5292984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5293984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5294cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5295cf5a6209SStefano 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]));
5296674ae819SStefano Zampini                   }
5297cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5298cf5a6209SStefano 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]));
5299984c4197SStefano Zampini                   }
5300984c4197SStefano Zampini                 }
5301984c4197SStefano Zampini               }
5302674ae819SStefano Zampini             } else {
530322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5304674ae819SStefano Zampini             }
5305674ae819SStefano Zampini           }
5306a717540cSStefano Zampini         } else { /* simple transformation block */
5307a717540cSStefano Zampini           PetscInt    row,col;
5308a6b551f4SStefano Zampini           PetscScalar val,norm;
5309a6b551f4SStefano Zampini 
5310a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
53119162d606SStefano 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));
5312a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
53139162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
53149162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5315bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
53169162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5317906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
53189162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5319a717540cSStefano Zampini             } else {
5320a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
53219162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5322a717540cSStefano Zampini                 if (row != col) {
53239162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5324a717540cSStefano Zampini                 } else {
53259162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5326a717540cSStefano Zampini                 }
5327906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5328a717540cSStefano Zampini               }
5329a717540cSStefano Zampini             }
5330a717540cSStefano Zampini           }
533198a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
533222d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5333a717540cSStefano Zampini           }
5334674ae819SStefano Zampini         }
5335984c4197SStefano Zampini       } else {
5336984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
53379162d606SStefano 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);
5338674ae819SStefano Zampini         }
5339674ae819SStefano Zampini       }
5340674ae819SStefano Zampini     }
5341a717540cSStefano Zampini 
5342a717540cSStefano Zampini     /* free workspace */
5343a717540cSStefano Zampini     if (qr_needed) {
5344984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5345cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5346984c4197SStefano Zampini       }
5347984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5348984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5349984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5350984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5351984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5352674ae819SStefano Zampini     }
5353a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5354906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5355906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5356906d46d4SStefano Zampini 
5357906d46d4SStefano Zampini     /* assembling of global change of variable */
535888c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5359bbb9e6c6SStefano Zampini       Mat      tmat;
536016f15bc4SStefano Zampini       PetscInt bs;
536116f15bc4SStefano Zampini 
5362906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5363906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5364bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5365bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5366bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5367bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
536816f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
536916f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5370906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5371bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5372bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5373bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5374bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5375bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5376e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5377e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5378bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5379bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
538088c03ad3SStefano Zampini 
5381906d46d4SStefano Zampini       /* check */
5382906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5383906d46d4SStefano Zampini         PetscReal error;
5384906d46d4SStefano Zampini         Vec       x,x_change;
5385906d46d4SStefano Zampini 
5386906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5387906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5388906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5389906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5390e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5391e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5392bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5393e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5394e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5395906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5396906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5397906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5398906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5399bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5400906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5401906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5402906d46d4SStefano Zampini       }
5403b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5404b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5405b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5406bf3a8328SStefano Zampini 
54079a962809SStefano 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);
5408b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5409ac632422SStefano Zampini           Mat                    S_new,tmat;
5410bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5411bbb9e6c6SStefano Zampini 
5412bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
54136816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5414bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5415bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5416bf3a8328SStefano Zampini             IS                     is_V;
5417b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5418b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5419b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5420b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5421b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5422bf3a8328SStefano Zampini           }
5423bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5424ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5425b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5426ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5427bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5428bf3a8328SStefano Zampini             const PetscScalar *array;
5429bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5430bf3a8328SStefano Zampini             PetscInt          i,n_V;
5431bf3a8328SStefano Zampini 
5432b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5433b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5434b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5435b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5436b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5437b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5438b087196eSStefano Zampini               PetscScalar val;
5439b087196eSStefano Zampini               PetscInt    idx;
5440b087196eSStefano Zampini 
5441b087196eSStefano Zampini               idx = idxs_V[i];
5442b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5443b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5444b087196eSStefano Zampini             }
5445b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5446b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5447bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5448bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5449bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5450bf3a8328SStefano Zampini           }
5451ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5452ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5453ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5454ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5455b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5456ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5457bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5458b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5459bf3a8328SStefano Zampini             }
5460ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5461ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5462ac632422SStefano Zampini           }
5463b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
546488c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5465b96c3477SStefano Zampini         }
5466c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5467b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5468c9db6a07SStefano Zampini           PetscInt i;
5469c9db6a07SStefano Zampini 
5470c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5471c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5472c9db6a07SStefano Zampini           }
5473c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5474c9db6a07SStefano Zampini         }
5475b96c3477SStefano Zampini       }
547616909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
547716909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
547816909a7fSStefano Zampini       } else {
5479906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
548016909a7fSStefano Zampini       }
54811dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
548227b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
548372b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
548472b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
548572b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
548672b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
548772b8c272SStefano Zampini     }
54881dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
548927b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5490b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5491b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5492906d46d4SStefano Zampini     } else {
54931dd7afcfSStefano Zampini       Mat benign_global = NULL;
549427b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
54951dd7afcfSStefano Zampini         Mat tmat;
54961dd7afcfSStefano Zampini 
54971dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
54981dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
54991dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
55001dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
55011dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
55021dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
55031dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
55041dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
55051dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
55061dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
55071dd7afcfSStefano Zampini           Mat M;
55081dd7afcfSStefano Zampini 
55091dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
55101dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
55111dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
55121dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5513906d46d4SStefano Zampini         } else {
55141dd7afcfSStefano Zampini           Mat         eye;
55151dd7afcfSStefano Zampini           PetscScalar *array;
55161dd7afcfSStefano Zampini 
55171dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
55181dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
55191dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
55201dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5521906d46d4SStefano Zampini           }
55221dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
55231dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55241dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55251dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
55261dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
55271dd7afcfSStefano Zampini         }
55281dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
55291dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
55301dd7afcfSStefano Zampini       }
55311dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
55321dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
55331dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
553427b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
55351dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
55361dd7afcfSStefano Zampini       }
55371dd7afcfSStefano Zampini     }
553816909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
553916909a7fSStefano Zampini       IS             is_global;
554016909a7fSStefano Zampini       const PetscInt *gidxs;
554116909a7fSStefano Zampini 
554216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
554316909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
554416909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
554516909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
554616909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
554716909a7fSStefano Zampini     }
55481dd7afcfSStefano Zampini   }
55491dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
55501dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5551b9b85e73SStefano Zampini   }
5552a717540cSStefano Zampini 
555372b8c272SStefano Zampini   if (!pcbddc->fake_change) {
55544f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
55554f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
55564f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
55574f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5558019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5559019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5560019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5561019a44ceSStefano Zampini     }
5562019a44ceSStefano Zampini 
5563019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5564727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5565727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
55669f47a83aSStefano 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);
5567c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
55680e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
55699f47a83aSStefano 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);
5570727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5571727cdba6SStefano Zampini       }
55720e6343abSStefano Zampini     }
5573727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5574b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
557572b8c272SStefano Zampini   }
557672b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5577727cdba6SStefano Zampini 
5578a717540cSStefano Zampini   /* flush dbg viewer */
5579b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5580b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5581b8ffe317SStefano Zampini   }
5582a717540cSStefano Zampini 
5583e310c8b4SStefano Zampini   /* free workspace */
5584a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
55854641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
558608122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
55879162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
55889162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
558908122e43SStefano Zampini   } else {
55909162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
55919162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
55929162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
559308122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
559408122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
55959162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
55969162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
559708122e43SStefano Zampini   }
5598674ae819SStefano Zampini   PetscFunctionReturn(0);
5599674ae819SStefano Zampini }
5600674ae819SStefano Zampini 
5601674ae819SStefano Zampini #undef __FUNCT__
5602674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5603674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5604674ae819SStefano Zampini {
560571582508SStefano Zampini   ISLocalToGlobalMapping map;
5606674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5607674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
560814f95afaSStefano Zampini   PetscInt               ierr,i,N;
5609674ae819SStefano Zampini 
5610674ae819SStefano Zampini   PetscFunctionBegin;
5611c8272957SStefano Zampini   if (pcbddc->graphanalyzed && !pcbddc->recompute_topography) PetscFunctionReturn(0);
56128e61c736SStefano Zampini   /* Reset previously computed graph */
56138e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5614674ae819SStefano Zampini   /* Init local Graph struct */
56157fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
561671582508SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5617*be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5618674ae819SStefano Zampini 
5619575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
56209a962809SStefano 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);
56219577ea80SStefano Zampini 
5622674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5623d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
56244d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
56254d379d7bSStefano Zampini     PetscInt  nvtxs;
5626e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
5627674ae819SStefano Zampini 
56282fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
56292fffb893SStefano Zampini     if (flg_row) {
56304d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5631b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
56322fffb893SStefano Zampini     }
56332fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5634674ae819SStefano Zampini   }
56359b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
56369b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5637674ae819SStefano Zampini   }
5638674ae819SStefano Zampini 
5639674ae819SStefano Zampini   /* Setup of Graph */
56404b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
564114f95afaSStefano 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);
5642674ae819SStefano Zampini 
56434f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
56444f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
56454f1b2e48SStefano Zampini     PetscInt *local_subs;
56464f1b2e48SStefano Zampini 
56474f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
56484f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
56494f1b2e48SStefano Zampini       const PetscInt *idxs;
56504f1b2e48SStefano Zampini       PetscInt       nl,j;
56514f1b2e48SStefano Zampini 
56524f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
56534f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
565471582508SStefano Zampini       for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
56554f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
56564f1b2e48SStefano Zampini     }
56574f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
56584f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
56594f1b2e48SStefano Zampini   }
56604f1b2e48SStefano Zampini 
5661674ae819SStefano Zampini   /* Graph's connected components analysis */
5662674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
566371582508SStefano Zampini 
566471582508SStefano Zampini   /* set flag indicating analysis has been done */
566571582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_TRUE;
5666674ae819SStefano Zampini   PetscFunctionReturn(0);
5667674ae819SStefano Zampini }
5668674ae819SStefano Zampini 
56699a7d3425SStefano Zampini #undef __FUNCT__
56709a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
56719a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
56729a7d3425SStefano Zampini {
56739a7d3425SStefano Zampini   PetscInt       i,j;
56749a7d3425SStefano Zampini   PetscScalar    *alphas;
56759a7d3425SStefano Zampini   PetscErrorCode ierr;
56769a7d3425SStefano Zampini 
56779a7d3425SStefano Zampini   PetscFunctionBegin;
5678785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
56799a7d3425SStefano Zampini   for (i=0;i<n;i++) {
56809a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5681669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5682669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5683669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
56849a7d3425SStefano Zampini   }
56859a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
56869a7d3425SStefano Zampini   PetscFunctionReturn(0);
56879a7d3425SStefano Zampini }
56889a7d3425SStefano Zampini 
5689e7931f94SStefano Zampini #undef __FUNCT__
569070cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
569157de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5692e7931f94SStefano Zampini {
569357de7509SStefano Zampini   Mat            A;
5694e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5695e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
569652e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
569752e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
569827b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
569957de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
570027b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
570127b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
570227b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
570327b6a85dSStefano Zampini   MPI_Comm       subcomm;
570452e5ac9dSStefano Zampini   PetscErrorCode ierr;
5705a57a6d2fSStefano Zampini 
5706e7931f94SStefano Zampini   PetscFunctionBegin;
570757de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
570857de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
570957de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
571057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
571157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
571257de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
571357de7509SStefano Zampini 
571457de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
571557de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
571657de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
571757de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
571857de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
571957de7509SStefano Zampini   im_active = !!(n);
572057de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
572157de7509SStefano Zampini   void_procs = size - active_procs;
572257de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
572357de7509SStefano Zampini   if (void_procs) {
572457de7509SStefano Zampini     PetscInt ncand;
572557de7509SStefano Zampini 
572657de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
572757de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
572857de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
572957de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
573057de7509SStefano Zampini       if (!procs_candidates[i]) {
573157de7509SStefano Zampini         procs_candidates[ncand++] = i;
573257de7509SStefano Zampini       }
573357de7509SStefano Zampini     }
573457de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
573557de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
573657de7509SStefano Zampini   }
573757de7509SStefano Zampini 
573814f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
573914f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
574014f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
574114f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
574214f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
574314f0bfb9SStefano Zampini     else dest = rank;
574457de7509SStefano Zampini     if (im_active) {
574557de7509SStefano Zampini       issize = 1;
574657de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
574714f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
574857de7509SStefano Zampini       } else {
574914f0bfb9SStefano Zampini         isidx = dest;
575057de7509SStefano Zampini       }
575157de7509SStefano Zampini     } else {
575257de7509SStefano Zampini       issize = 0;
575357de7509SStefano Zampini       isidx = -1;
575457de7509SStefano Zampini     }
575557de7509SStefano Zampini     *n_subdomains = active_procs;
575657de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
5757daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
575857de7509SStefano Zampini     PetscFunctionReturn(0);
575957de7509SStefano Zampini   }
5760c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
5761c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
576227b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
5763e7931f94SStefano Zampini 
5764e7931f94SStefano Zampini   /* Get info on mapping */
57653bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
57663bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5767e7931f94SStefano Zampini 
5768e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
5769785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
5770e7931f94SStefano Zampini   xadj[0] = 0;
5771e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
5772785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
5773785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
577427b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
577527b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
577627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
577727b6a85dSStefano Zampini       count[shared[i][j]] += 1;
5778e7931f94SStefano Zampini 
577927b6a85dSStefano Zampini   xadj_count = 0;
57802b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
578127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
578227b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
5783d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
5784d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
5785d023bfaeSStefano Zampini         xadj_count++;
578627b6a85dSStefano Zampini         break;
578727b6a85dSStefano Zampini       }
5788e7931f94SStefano Zampini     }
5789e7931f94SStefano Zampini   }
5790d023bfaeSStefano Zampini   xadj[1] = xadj_count;
579127b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
57923bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5793e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
5794e7931f94SStefano Zampini 
57953837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
5796e7931f94SStefano Zampini 
579727b6a85dSStefano Zampini   /* Restrict work on active processes only */
579827b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
579927b6a85dSStefano Zampini   if (void_procs) {
580027b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
580127b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
580227b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
580327b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
580427b6a85dSStefano Zampini   } else {
580527b6a85dSStefano Zampini     psubcomm = NULL;
580627b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
580727b6a85dSStefano Zampini   }
580827b6a85dSStefano Zampini 
580927b6a85dSStefano Zampini   v_wgt = NULL;
581027b6a85dSStefano Zampini   if (!color) {
5811e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5812e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5813e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5814c8587f34SStefano Zampini   } else {
581552e5ac9dSStefano Zampini     Mat             subdomain_adj;
581652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
581752e5ac9dSStefano Zampini     MatPartitioning partitioner;
581827b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
581952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
582057de7509SStefano Zampini     PetscMPIInt     size;
5821b0c7d250SStefano Zampini     PetscBool       aggregate;
5822b0c7d250SStefano Zampini 
582327b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
582427b6a85dSStefano Zampini     if (void_procs) {
582527b6a85dSStefano Zampini       PetscInt prank = rank;
5826785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
582727b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5828e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5829e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5830c8587f34SStefano Zampini       }
5831e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
583227b6a85dSStefano Zampini     } else {
583327b6a85dSStefano Zampini       oldranks = NULL;
583427b6a85dSStefano Zampini     }
5835b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
583627b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5837b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5838b0c7d250SStefano Zampini       PetscMPIInt nrank;
5839b0c7d250SStefano Zampini       PetscScalar *vals;
5840b0c7d250SStefano Zampini 
584127b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5842b0c7d250SStefano Zampini       lrows = 0;
5843b0c7d250SStefano Zampini       if (nrank<redprocs) {
5844b0c7d250SStefano Zampini         lrows = size/redprocs;
5845b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5846b0c7d250SStefano Zampini       }
584727b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5848b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5849b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5850b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5851b0c7d250SStefano Zampini       row = nrank;
5852b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5853b0c7d250SStefano Zampini       cols = adjncy;
5854b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5855b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5856b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5857b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5858b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
585952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
586052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
586152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5862b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
586327b6a85dSStefano Zampini       if (use_vwgt) {
586427b6a85dSStefano Zampini         Vec               v;
586527b6a85dSStefano Zampini         const PetscScalar *array;
586627b6a85dSStefano Zampini         PetscInt          nl;
586727b6a85dSStefano Zampini 
586827b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
586927b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
587027b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
587127b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
587227b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
587327b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
587427b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
587522db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
587627b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
587727b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
587827b6a85dSStefano Zampini       }
5879b0c7d250SStefano Zampini     } else {
588027b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
588127b6a85dSStefano Zampini       if (use_vwgt) {
588227b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
588327b6a85dSStefano Zampini         v_wgt[0] = local_size;
588427b6a85dSStefano Zampini       }
5885b0c7d250SStefano Zampini     }
588622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5887e7931f94SStefano Zampini 
5888e7931f94SStefano Zampini     /* Partition */
588927b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5890e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
589127b6a85dSStefano Zampini     if (v_wgt) {
5892e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5893c8587f34SStefano Zampini     }
589457de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
589557de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5896e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5897e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
589822b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5899e7931f94SStefano Zampini 
590052e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
59016583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
590252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
590352e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
590457de7509SStefano Zampini     if (!aggregate) {
590557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
590627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
590727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
590827b6a85dSStefano Zampini #endif
590957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
591027b6a85dSStefano Zampini       } else if (oldranks) {
5911b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
591227b6a85dSStefano Zampini       } else {
591327b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
591457de7509SStefano Zampini       }
591528143c3dSStefano Zampini     } else {
5916b0c7d250SStefano Zampini       PetscInt    idxs[1];
5917b0c7d250SStefano Zampini       PetscMPIInt tag;
5918b0c7d250SStefano Zampini       MPI_Request *reqs;
5919b0c7d250SStefano Zampini 
5920b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5921b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5922b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
592327b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
592428143c3dSStefano Zampini       }
592527b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5926b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5927b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
592857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
592927b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
593027b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
593127b6a85dSStefano Zampini #endif
593257de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
593327b6a85dSStefano Zampini       } else if (oldranks) {
5934b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
593527b6a85dSStefano Zampini       } else {
593627b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5937e7931f94SStefano Zampini       }
593857de7509SStefano Zampini     }
593952e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5940e7931f94SStefano Zampini     /* clean up */
5941e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
594252e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5943e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5944e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5945e7931f94SStefano Zampini   }
594627b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
594757de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5948e7931f94SStefano Zampini 
5949e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5950e7931f94SStefano Zampini   i = 1;
595127b6a85dSStefano Zampini   if (!color) i=0;
595257de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5953e7931f94SStefano Zampini   PetscFunctionReturn(0);
5954e7931f94SStefano Zampini }
5955e7931f94SStefano Zampini 
5956e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5957e7931f94SStefano Zampini 
5958e7931f94SStefano Zampini #undef __FUNCT__
5959e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
59601ae86dd6SStefano 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[])
5961e7931f94SStefano Zampini {
596270cf5478SStefano Zampini   Mat                    local_mat;
5963e7931f94SStefano Zampini   IS                     is_sends_internal;
59649d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
59651ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
59669d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5967e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5968e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5969e7931f94SStefano Zampini   const PetscInt*        is_indices;
5970e7931f94SStefano Zampini   MatType                new_local_type;
5971e7931f94SStefano Zampini   /* buffers */
5972e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
597328143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
59749d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5975e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
59761ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
5977e7931f94SStefano Zampini   /* MPI */
597828143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
597928143c3dSStefano Zampini   PetscSubcomm           subcomm;
5980e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
598128143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
598228143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
59831ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
59841ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
59851ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
5986e7931f94SStefano Zampini   PetscErrorCode         ierr;
5987e7931f94SStefano Zampini 
5988e7931f94SStefano Zampini   PetscFunctionBegin;
598957de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5990e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
599128143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
599257de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
599357de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
599457de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
599557de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
599657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
59971ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
59981ae86dd6SStefano Zampini   if (nvecs) {
59991ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
60001ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
60011ae86dd6SStefano Zampini   }
600257de7509SStefano Zampini   /* further checks */
6003e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6004e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6005e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6006e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6007e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
600857de7509SStefano Zampini   if (reuse && *mat_n) {
600970cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
601057de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
601170cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
601228143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
601370cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
601470cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
601570cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
601670cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
601770cf5478SStefano Zampini   }
6018e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6019e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
602057de7509SStefano Zampini 
6021e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6022e7931f94SStefano Zampini   if (!is_sends) {
602328143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
602457de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6025c8587f34SStefano Zampini   } else {
6026e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6027e7931f94SStefano Zampini     is_sends_internal = is_sends;
6028c8587f34SStefano Zampini   }
6029e7931f94SStefano Zampini 
6030e7931f94SStefano Zampini   /* get comm */
6031a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6032e7931f94SStefano Zampini 
6033e7931f94SStefano Zampini   /* compute number of sends */
6034e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6035e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6036e7931f94SStefano Zampini 
6037e7931f94SStefano Zampini   /* compute number of receives */
6038e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6039785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6040e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6041e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6042e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6043e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6044e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6045e7931f94SStefano Zampini 
604628143c3dSStefano Zampini   /* restrict comm if requested */
604728143c3dSStefano Zampini   subcomm = 0;
604828143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
604928143c3dSStefano Zampini   if (restrict_comm) {
6050779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6051779c1cceSStefano Zampini 
605228143c3dSStefano Zampini     color = 0;
605353a05cb3SStefano Zampini     if (restrict_full) {
605453a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
605553a05cb3SStefano Zampini     } else {
605653a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
605753a05cb3SStefano Zampini     }
6058b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
605928143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
606028143c3dSStefano Zampini     /* check if reuse has been requested */
606157de7509SStefano Zampini     if (reuse) {
606228143c3dSStefano Zampini       if (*mat_n) {
606328143c3dSStefano Zampini         PetscMPIInt subcommsize2;
606428143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
606528143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
606628143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
606728143c3dSStefano Zampini       } else {
606828143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
606928143c3dSStefano Zampini       }
607028143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6071779c1cceSStefano Zampini       PetscMPIInt rank;
6072779c1cceSStefano Zampini 
6073779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
607428143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
607528143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
607628143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6077306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
607828143c3dSStefano Zampini     }
607928143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
608028143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
608128143c3dSStefano Zampini   } else {
608228143c3dSStefano Zampini     comm_n = comm;
608328143c3dSStefano Zampini   }
608428143c3dSStefano Zampini 
6085e7931f94SStefano Zampini   /* prepare send/receive buffers */
6086785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6087e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6088785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6089e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
609028143c3dSStefano Zampini   if (nis) {
6091854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
609228143c3dSStefano Zampini   }
6093e7931f94SStefano Zampini 
609428143c3dSStefano Zampini   /* Get data from local matrices */
60956c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6096e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6097e7931f94SStefano Zampini     /*
6098e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6099e7931f94SStefano Zampini        send_buffer_idxs should contain:
6100e7931f94SStefano Zampini        - MatType_PRIVATE type
6101e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6102e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6103e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6104e7931f94SStefano Zampini     */
61056c4ed002SBarry Smith   else {
6106e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
61073bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6108854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6109e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6110e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
61113bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6112e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
61133bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6114e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6115e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6116e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6117e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6118c8587f34SStefano Zampini     }
6119c8587f34SStefano Zampini   }
6120e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
612128143c3dSStefano Zampini   /* additional is (if any) */
612228143c3dSStefano Zampini   if (nis) {
612328143c3dSStefano Zampini     PetscMPIInt psum;
612428143c3dSStefano Zampini     PetscInt j;
612528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
612628143c3dSStefano Zampini       PetscInt plen;
612728143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
612828143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
612928143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
613028143c3dSStefano Zampini     }
6131854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
613228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
613328143c3dSStefano Zampini       PetscInt plen;
613428143c3dSStefano Zampini       const PetscInt *is_array_idxs;
613528143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
613628143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
613728143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
613828143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
613928143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
614028143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
614128143c3dSStefano Zampini     }
614228143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
614328143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
614428143c3dSStefano Zampini     }
614528143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
614628143c3dSStefano Zampini   }
614728143c3dSStefano Zampini 
6148e7931f94SStefano Zampini   buf_size_idxs = 0;
6149e7931f94SStefano Zampini   buf_size_vals = 0;
615028143c3dSStefano Zampini   buf_size_idxs_is = 0;
61511ae86dd6SStefano Zampini   buf_size_vecs = 0;
6152e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6153e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6154e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
615528143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
61561ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6157e7931f94SStefano Zampini   }
6158785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6159785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
616095ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
61611ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6162e7931f94SStefano Zampini 
6163e7931f94SStefano Zampini   /* get new tags for clean communications */
6164e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6165e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
616628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
61671ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6168e7931f94SStefano Zampini 
6169e7931f94SStefano Zampini   /* allocate for requests */
6170785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6171785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
617295ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
61731ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6174785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6175785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
617695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
61771ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6178e7931f94SStefano Zampini 
6179e7931f94SStefano Zampini   /* communications */
6180e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6181e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
618228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
61831ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6184e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6185e7931f94SStefano Zampini     source_dest = onodes[i];
6186e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6187e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6188e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6189e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
619028143c3dSStefano Zampini     if (nis) {
619157de7509SStefano Zampini       source_dest = onodes_is[i];
619228143c3dSStefano 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);
619328143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
619428143c3dSStefano Zampini     }
61951ae86dd6SStefano Zampini     if (nvecs) {
61961ae86dd6SStefano Zampini       source_dest = onodes[i];
61971ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
61981ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
61991ae86dd6SStefano Zampini     }
6200e7931f94SStefano Zampini   }
6201e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6202e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6203e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6204e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
620528143c3dSStefano Zampini     if (nis) {
620628143c3dSStefano 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);
620728143c3dSStefano Zampini     }
62081ae86dd6SStefano Zampini     if (nvecs) {
62091ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
62101ae86dd6SStefano 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);
62111ae86dd6SStefano Zampini     }
6212e7931f94SStefano Zampini   }
6213e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6214e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6215e7931f94SStefano Zampini 
6216e7931f94SStefano Zampini   /* assemble new l2g map */
6217e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6218e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
62199d30be91SStefano Zampini   new_local_rows = 0;
6220e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
62219d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6222e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6223e7931f94SStefano Zampini   }
62249d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6225e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
62269d30be91SStefano Zampini   new_local_rows = 0;
6227e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
62289d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
62299d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6230e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6231e7931f94SStefano Zampini   }
62329d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
62339d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6234e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6235e7931f94SStefano Zampini 
6236e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6237e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6238e7931f94SStefano 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) */
6239e7931f94SStefano Zampini   if (n_recvs) {
624028143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6241e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6242e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6243e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6244e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6245e7931f94SStefano Zampini         break;
6246e7931f94SStefano Zampini       }
6247e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6248e7931f94SStefano Zampini     }
6249e7931f94SStefano Zampini     switch (new_local_type_private) {
625028143c3dSStefano Zampini       case MATDENSE_PRIVATE:
625128143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6252e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6253e7931f94SStefano Zampini           bs = 1;
625428143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
625528143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
625628143c3dSStefano Zampini           bs = 1;
625728143c3dSStefano Zampini         }
6258e7931f94SStefano Zampini         break;
6259e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6260e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6261e7931f94SStefano Zampini         bs = 1;
6262e7931f94SStefano Zampini         break;
6263e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6264e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6265e7931f94SStefano Zampini         break;
6266e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6267e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6268e7931f94SStefano Zampini         break;
6269e7931f94SStefano Zampini       default:
62709d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6271e7931f94SStefano Zampini         break;
6272e7931f94SStefano Zampini     }
627328143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
627428143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
627528143c3dSStefano Zampini     bs = 1;
6276e7931f94SStefano Zampini   }
6277e7931f94SStefano Zampini 
627870cf5478SStefano Zampini   /* create MATIS object if needed */
627957de7509SStefano Zampini   if (!reuse) {
6280e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6281e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
628270cf5478SStefano Zampini   } else {
628370cf5478SStefano Zampini     /* it also destroys the local matrices */
628457de7509SStefano Zampini     if (*mat_n) {
628570cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
628657de7509SStefano Zampini     } else { /* this is a fake object */
628757de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
628857de7509SStefano Zampini     }
628970cf5478SStefano Zampini   }
629070cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6291e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
62929d30be91SStefano Zampini 
62939d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
62949d30be91SStefano Zampini 
62959d30be91SStefano Zampini   /* Global to local map of received indices */
62969d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
62979d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
62989d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
62999d30be91SStefano Zampini 
63009d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
63019d30be91SStefano Zampini   buf_size_idxs = 0;
63029d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
63039d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
63049d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
63059d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
63069d30be91SStefano Zampini   }
63079d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
63089d30be91SStefano Zampini 
63099d30be91SStefano Zampini   /* set preallocation */
63109d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
63119d30be91SStefano Zampini   if (!newisdense) {
63129d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
63139d30be91SStefano Zampini 
63149d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
63159d30be91SStefano Zampini     if (n_recvs) {
63169d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
63179d30be91SStefano Zampini     }
63189d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
63199d30be91SStefano Zampini       PetscInt j;
63209d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
63219d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
63229d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
63239d30be91SStefano Zampini         }
63249d30be91SStefano Zampini       } else {
63259d30be91SStefano Zampini         /* TODO */
63269d30be91SStefano Zampini       }
63279d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
63289d30be91SStefano Zampini     }
63299d30be91SStefano Zampini     if (new_local_nnz) {
63309d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
63319d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
63329d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
63339d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
63349d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
63359d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
63369d30be91SStefano Zampini     } else {
63379d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
63389d30be91SStefano Zampini     }
63399d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
63409d30be91SStefano Zampini   } else {
63419d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
63429d30be91SStefano Zampini   }
6343e7931f94SStefano Zampini 
6344e7931f94SStefano Zampini   /* set values */
6345e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
63469d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6347e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6348e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6349e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
63509d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6351e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6352e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6353e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
635428143c3dSStefano Zampini     } else {
635528143c3dSStefano Zampini       /* TODO */
6356e7931f94SStefano Zampini     }
6357e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6358e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6359e7931f94SStefano Zampini   }
6360e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6361e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
636270cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
636370cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63649d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6365e7931f94SStefano Zampini 
6366dfd14d43SStefano Zampini #if 0
636728143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6368e7931f94SStefano Zampini     Vec       lvec,rvec;
6369e7931f94SStefano Zampini     PetscReal infty_error;
6370e7931f94SStefano Zampini 
63712a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6372e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6373e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6374e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
637570cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6376e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6377e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6378e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6379e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6380e7931f94SStefano Zampini   }
638128143c3dSStefano Zampini #endif
6382e7931f94SStefano Zampini 
638328143c3dSStefano Zampini   /* assemble new additional is (if any) */
638428143c3dSStefano Zampini   if (nis) {
638528143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
638628143c3dSStefano Zampini 
638728143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6388854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
638928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
639028143c3dSStefano Zampini     psum = 0;
639128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
639228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
639328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
639428143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
639528143c3dSStefano Zampini         psum += plen;
639628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
639728143c3dSStefano Zampini       }
639828143c3dSStefano Zampini     }
6399854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6400854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
640128143c3dSStefano Zampini     for (i=1;i<nis;i++) {
640228143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
640328143c3dSStefano Zampini     }
640428143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
640528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
640628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
640728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
640828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
640928143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
641028143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
641128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
641228143c3dSStefano Zampini       }
641328143c3dSStefano Zampini     }
641428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
641528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
641628143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
641728143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
641828143c3dSStefano Zampini     }
641928143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
642028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
642128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
642228143c3dSStefano Zampini   }
6423e7931f94SStefano Zampini   /* free workspace */
642428143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6425e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6426e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6427e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6428e7931f94SStefano Zampini   if (isdense) {
6429e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6430e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6431e7931f94SStefano Zampini   } else {
6432e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6433e7931f94SStefano Zampini   }
643428143c3dSStefano Zampini   if (nis) {
643528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
643628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
643728143c3dSStefano Zampini   }
64381ae86dd6SStefano Zampini 
64391ae86dd6SStefano Zampini   if (nvecs) {
64401ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
64411ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
64421ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64431ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
64441ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
64451ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
64461ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
64471ae86dd6SStefano Zampini     /* set values */
64481ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
64491ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
64501ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64511ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
64521ae86dd6SStefano Zampini       PetscInt j;
64531ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
64541ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
64551ae86dd6SStefano Zampini       }
64561ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
64571ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
64581ae86dd6SStefano Zampini     }
64591ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64601ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
64611ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
64621ae86dd6SStefano Zampini   }
64631ae86dd6SStefano Zampini 
64641ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
64651ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6466e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6467e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
64681ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
646928143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6470e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6471e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
64721ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
647328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6474e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6475e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6476e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6477e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6478e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
647928143c3dSStefano Zampini   if (nis) {
648028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
648128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
648228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
648328143c3dSStefano Zampini   }
648428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
648528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
648628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
648728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
648828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
648928143c3dSStefano Zampini     }
64901ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
64911ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
64921ae86dd6SStefano Zampini     }
649353a05cb3SStefano Zampini     *mat_n = NULL;
649428143c3dSStefano Zampini   }
6495e7931f94SStefano Zampini   PetscFunctionReturn(0);
6496e7931f94SStefano Zampini }
6497a57a6d2fSStefano Zampini 
649812edc857SStefano Zampini /* temporary hack into ksp private data structure */
6499af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
650012edc857SStefano Zampini 
6501c8587f34SStefano Zampini #undef __FUNCT__
6502c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6503c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6504c8587f34SStefano Zampini {
6505c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6506c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
650720a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
65081ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
65099881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
651020a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
65116e683305SStefano Zampini   IS                     coarse_is,*isarray;
65126e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
651330368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6514f9eb5b7dSStefano Zampini   PC                     pc_temp;
6515c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6516c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6517f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
65184f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
65196e683305SStefano Zampini   Mat                    t_coarse_mat_is;
652057de7509SStefano Zampini   PetscInt               ncoarse;
652168457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
652222bc73bbSStefano Zampini   PetscScalar            *array;
652357de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
652457de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
65259881197aSStefano Zampini   PetscErrorCode         ierr;
6526fdc09c96SStefano Zampini 
6527c8587f34SStefano Zampini   PetscFunctionBegin;
6528c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
652968457ee5SStefano 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 */
6530fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
65315a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6532fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6533f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6534f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6535f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6536fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
653751bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
653851bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6539dc4bcba2SStefano Zampini         PC        pc;
6540dc4bcba2SStefano Zampini         PetscBool isbddc;
6541dc4bcba2SStefano Zampini 
6542dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6543dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6544dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6545dc4bcba2SStefano Zampini         if (isbddc) {
654663c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
654763c961adSStefano Zampini         } else {
6548727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
654963c961adSStefano Zampini         }
6550fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6551fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6552fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6553f4ddd8eeSStefano Zampini       }
6554fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6555fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6556f4ddd8eeSStefano Zampini     }
655770cf5478SStefano Zampini     /* reset any subassembling information */
655857de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
655970cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
656057de7509SStefano Zampini     }
65616e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6562fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6563f4ddd8eeSStefano Zampini   }
656457de7509SStefano Zampini   /* assemble coarse matrix */
656557de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
656657de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
656757de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
656857de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
656918a45a71SStefano Zampini   } else {
657057de7509SStefano Zampini     coarse_mat = NULL;
657157de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
65726e683305SStefano Zampini   }
6573e7931f94SStefano Zampini 
6574abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6575abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6576abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6577abbbba34SStefano Zampini 
6578abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
657922bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
658022bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
658122bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
658222bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6583e176bc59SStefano 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);
65846e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
65856e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65866e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6587abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6588abbbba34SStefano Zampini 
658957de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
659057de7509SStefano Zampini   im_active = !!(pcis->n);
659157de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
659257de7509SStefano Zampini 
659314f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
659457de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
659557de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
659657de7509SStefano Zampini   coarse_mat_is = NULL;
659757de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
659857de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
659957de7509SStefano Zampini   full_restr = PETSC_TRUE;
66001ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
660157de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
660257de7509SStefano Zampini   if (multilevel_requested) {
660357de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
660457de7509SStefano Zampini     restr = PETSC_FALSE;
660557de7509SStefano Zampini     full_restr = PETSC_FALSE;
660657de7509SStefano Zampini   } else {
660757de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
660857de7509SStefano Zampini     restr = PETSC_TRUE;
660957de7509SStefano Zampini     full_restr = PETSC_TRUE;
661057de7509SStefano Zampini   }
66114b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
661257de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
661357de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6614a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
661557de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6616a198735bSStefano Zampini     } else {
6617a198735bSStefano Zampini       PetscMPIInt size,rank;
6618a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6619a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6620a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6621a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6622a198735bSStefano Zampini     }
662357de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
662457de7509SStefano Zampini     PetscInt    psum;
662557de7509SStefano Zampini     PetscMPIInt size;
662657de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
662757de7509SStefano Zampini     else psum = 0;
662857de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
662957de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
663057de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
663157de7509SStefano Zampini   }
663257de7509SStefano Zampini   /* determine if we can go multilevel */
663357de7509SStefano Zampini   if (multilevel_requested) {
663457de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
663557de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
663657de7509SStefano Zampini   }
663757de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
663857de7509SStefano Zampini 
6639e4d548c7SStefano Zampini   /* dump subassembling pattern */
6640e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6641e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6642e4d548c7SStefano Zampini   }
6643e4d548c7SStefano Zampini 
66446e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
664527b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
66466e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
66476e683305SStefano Zampini     const PetscInt         *idxs;
66486e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
66496e683305SStefano Zampini 
66506e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
66510be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
66526e683305SStefano Zampini     /* allocate space for temporary storage */
6653854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6654854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
66556e683305SStefano Zampini     /* allocate for IS array */
66566e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
66576e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
665827b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
665930368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6660854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
66616e683305SStefano Zampini     /* dofs splitting */
66626e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
66636e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
66646e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
66656e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
66666e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
66676e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
66686e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
666930368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
66706e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
66716e683305SStefano Zampini     }
66726e683305SStefano Zampini     /* neumann boundaries */
66736e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
66746e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
66756e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
66766e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
66776e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
66786e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
66796e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
668030368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
66816e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
66826e683305SStefano Zampini     }
66836e683305SStefano Zampini     /* free memory */
66846e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
66856e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
66866e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
66876e683305SStefano Zampini   } else {
66886e683305SStefano Zampini     nis = 0;
66896e683305SStefano Zampini     nisdofs = 0;
66906e683305SStefano Zampini     nisneu = 0;
669130368db7SStefano Zampini     nisvert = 0;
66926e683305SStefano Zampini     isarray = NULL;
66936e683305SStefano Zampini   }
66946e683305SStefano Zampini   /* destroy no longer needed map */
66956e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
66966e683305SStefano Zampini 
669757de7509SStefano Zampini   /* subassemble */
669857de7509SStefano Zampini   if (multilevel_allowed) {
66991ae86dd6SStefano Zampini     Vec       vp[1];
67001ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
670157de7509SStefano Zampini     PetscBool reuse,reuser;
67021ae86dd6SStefano Zampini 
670357de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
670457de7509SStefano Zampini     else reuse = PETSC_FALSE;
670557de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
67061ae86dd6SStefano Zampini     vp[0] = NULL;
67071ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
67081ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
67091ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
67101ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
67111ae86dd6SStefano Zampini       nvecs = 1;
67121ae86dd6SStefano Zampini 
67131ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6714a198735bSStefano Zampini         Mat      B,loc_divudotp;
67151ae86dd6SStefano Zampini         Vec      v,p;
67161ae86dd6SStefano Zampini         IS       dummy;
67171ae86dd6SStefano Zampini         PetscInt np;
67181ae86dd6SStefano Zampini 
6719a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6720a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
67211ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6722a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
67231ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
67241ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
67251ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
67261ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
67271ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
67281ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
67291ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
67301ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
67311ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
67321ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
67331ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
67341ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
673574e2c79eSStefano Zampini       }
67361ae86dd6SStefano Zampini     }
67371ae86dd6SStefano Zampini     if (reuser) {
67381ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
673974e2c79eSStefano Zampini     } else {
67401ae86dd6SStefano 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);
67411ae86dd6SStefano Zampini     }
67421ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
67431ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
67441ae86dd6SStefano Zampini       PetscInt    nl;
67451ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
67461ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
67471ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
67481ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
67491ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
67501ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
67511ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
67521ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
6753a198735bSStefano Zampini     } else {
6754a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
67551ae86dd6SStefano Zampini     }
67561ae86dd6SStefano Zampini   } else {
67571ae86dd6SStefano 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);
67586e683305SStefano Zampini   }
675957de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
676057de7509SStefano Zampini     PetscMPIInt size;
676157de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
676257de7509SStefano Zampini     if (!multilevel_allowed) {
676357de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
67646e683305SStefano Zampini     } else {
676557de7509SStefano Zampini       Mat A;
6766779c1cceSStefano Zampini 
676757de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
676857de7509SStefano Zampini       if (coarse_mat_is) {
676957de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
677057de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
677157de7509SStefano Zampini         coarse_mat = coarse_mat_is;
677257de7509SStefano Zampini       }
677357de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
677457de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
677557de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
6776779c1cceSStefano Zampini     }
6777779c1cceSStefano Zampini   }
677857de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
677957de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
67806e683305SStefano Zampini 
67816e683305SStefano Zampini   /* create local to global scatters for coarse problem */
678268457ee5SStefano Zampini   if (compute_vecs) {
67836e683305SStefano Zampini     PetscInt lrows;
67846e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
678557de7509SStefano Zampini     if (coarse_mat) {
678657de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
67876e683305SStefano Zampini     } else {
67886e683305SStefano Zampini       lrows = 0;
67896e683305SStefano Zampini     }
67906e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
67916e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
67926e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
67936e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
67946e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
67956e683305SStefano Zampini   }
67966e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
6797c8587f34SStefano Zampini 
6798f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
6799f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
6800f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
6801f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
6802f9eb5b7dSStefano Zampini   } else {
6803f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
6804f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
6805c8587f34SStefano Zampini   }
6806c8587f34SStefano Zampini 
68076e683305SStefano Zampini   /* print some info if requested */
68086e683305SStefano Zampini   if (pcbddc->dbg_flag) {
68096e683305SStefano Zampini     if (!multilevel_allowed) {
68106e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
68116e683305SStefano Zampini       if (multilevel_requested) {
68126e683305SStefano 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);
68136e683305SStefano Zampini       } else if (pcbddc->max_levels) {
68146e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
68156e683305SStefano Zampini       }
68166e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
68176e683305SStefano Zampini     }
68186e683305SStefano Zampini   }
68196e683305SStefano Zampini 
6820f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
682157de7509SStefano Zampini   if (coarse_mat) {
68226a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
68236e683305SStefano Zampini     if (pcbddc->dbg_flag) {
682457de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
68256e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
68266e683305SStefano Zampini     }
6827f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
6828312be037SStefano Zampini       char prefix[256],str_level[16];
6829e604994aSStefano Zampini       size_t len;
683057de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
6831422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
6832c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
6833f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
683457de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6835c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
68366e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
6837c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
6838c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6839e604994aSStefano Zampini       /* prefix */
6840e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
6841e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
6842e604994aSStefano Zampini       if (!pcbddc->current_level) {
6843e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
6844e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
6845c8587f34SStefano Zampini       } else {
6846e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
6847312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
6848312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
684934d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
6850312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
6851e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
6852e604994aSStefano Zampini       }
6853e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
68543e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
68553e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
68563e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
68573e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
6858f9eb5b7dSStefano Zampini       /* allow user customization */
6859f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
68603e3c6dadSStefano Zampini     }
68613e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
686251bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
68633e3c6dadSStefano Zampini     if (nisdofs) {
68643e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
68653e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
68663e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
68673e3c6dadSStefano Zampini       }
68683e3c6dadSStefano Zampini     }
68693e3c6dadSStefano Zampini     if (nisneu) {
68703e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
68713e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
6872312be037SStefano Zampini     }
687330368db7SStefano Zampini     if (nisvert) {
687430368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
687530368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
687630368db7SStefano Zampini     }
6877f9eb5b7dSStefano Zampini 
6878f9eb5b7dSStefano Zampini     /* get some info after set from options */
6879f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
6880f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
68814f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
68826e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
6883f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6884f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
6885f9eb5b7dSStefano Zampini     }
688639f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
68874f3a063dSStefano Zampini     if (isredundant) {
68884f3a063dSStefano Zampini       KSP inner_ksp;
68894f3a063dSStefano Zampini       PC  inner_pc;
68904f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
68914f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
68924f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
68934f3a063dSStefano Zampini     }
6894f9eb5b7dSStefano Zampini 
689557de7509SStefano Zampini     /* parameters which miss an API */
689657de7509SStefano Zampini     if (isbddc) {
6897720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
6898720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
689957de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
690027b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
690127b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
6902a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
6903a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
6904a198735bSStefano Zampini         IS                     row,col;
6905a198735bSStefano Zampini         const PetscInt         *gidxs;
6906a198735bSStefano Zampini         PetscInt               n,st,M,N;
6907a198735bSStefano Zampini 
6908a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
6909a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
6910a198735bSStefano Zampini         st = st-n;
6911a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
6912a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
6913a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
6914a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6915a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
6916a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6917a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
6918a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
6919a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
6920a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
6921a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
6922a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
6923a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
6924a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
6925a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
6926a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
6927a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6928a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6929a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
6930a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
69318ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
6932a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
6933720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
693459e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6935720d30f9SStefano Zampini       }
6936d4d8cf7bSStefano Zampini     }
69379881197aSStefano Zampini 
69383301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
69395a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
69403301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
69413301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
69423301b35fSStefano Zampini     }
69433301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
69443301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
69453301b35fSStefano Zampini     }
69463301b35fSStefano Zampini     if (pc->pmat->spd_set) {
69473301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
69483301b35fSStefano Zampini     }
694927b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
695027b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
695127b6a85dSStefano Zampini     }
69526e683305SStefano Zampini     /* set operators */
69535f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
69546e683305SStefano Zampini     if (pcbddc->dbg_flag) {
69556e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
69566e683305SStefano Zampini     }
69576e683305SStefano Zampini   }
69586e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6959b1ecc7b1SStefano Zampini #if 0
6960b9b85e73SStefano Zampini   {
6961b9b85e73SStefano Zampini     PetscViewer viewer;
6962b9b85e73SStefano Zampini     char filename[256];
6963b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6964b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
69656a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6966b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6967f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6968b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6969b9b85e73SStefano Zampini   }
6970b9b85e73SStefano Zampini #endif
6971f9eb5b7dSStefano Zampini 
697298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
697398a51de6SStefano Zampini     Vec crhs,csol;
697404708bb6SStefano Zampini 
6975f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6976f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6977f347579bSStefano Zampini     if (!csol) {
69782a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6979f9eb5b7dSStefano Zampini     }
6980f347579bSStefano Zampini     if (!crhs) {
69812a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6982f347579bSStefano Zampini     }
6983b0f5fe93SStefano Zampini   }
69841ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6985b0f5fe93SStefano Zampini 
6986b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6987b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6988b0f5fe93SStefano Zampini 
6989b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
69904f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
69914f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
69924f1b2e48SStefano Zampini     }
6993b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6994b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6995b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6996b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6997b0f5fe93SStefano Zampini     if (coarse_mat) {
6998b0f5fe93SStefano Zampini       Vec         nullv;
6999b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7000b0f5fe93SStefano Zampini       PetscInt    nl;
7001b0f5fe93SStefano Zampini 
7002b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7003b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7004b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7005b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7006b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7007b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7008b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7009b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7010b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7011b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7012b0f5fe93SStefano Zampini     }
7013b0f5fe93SStefano Zampini   }
7014b0f5fe93SStefano Zampini 
7015b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7016b0f5fe93SStefano Zampini     PetscBool ispreonly;
7017b0f5fe93SStefano Zampini 
7018b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7019b0f5fe93SStefano Zampini       PetscBool isnull;
7020b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7021bef83e63SStefano Zampini       if (isnull) {
7022b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7023b0f5fe93SStefano Zampini       }
7024bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7025b0f5fe93SStefano Zampini     }
7026b0f5fe93SStefano Zampini     /* setup coarse ksp */
7027b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7028cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7029cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
70306e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7031c8587f34SStefano Zampini       KSP       check_ksp;
70322b510759SStefano Zampini       KSPType   check_ksp_type;
7033c8587f34SStefano Zampini       PC        check_pc;
70346e683305SStefano Zampini       Vec       check_vec,coarse_vec;
70356a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
70362b510759SStefano Zampini       PetscInt  its;
70376e683305SStefano Zampini       PetscBool compute_eigs;
70386e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
70396e683305SStefano Zampini       PetscInt  neigs;
70408e185a42SStefano Zampini       const char *prefix;
7041c8587f34SStefano Zampini 
70422b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
70436e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7044422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
704523ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7046f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7047e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7048e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7049e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
70502b510759SStefano Zampini       if (ispreonly) {
70512b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
70526e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
70532b510759SStefano Zampini       } else {
7054cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
70556e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7056c8587f34SStefano Zampini       }
7057c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
70586e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
70596e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
70606e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7061a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7062a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7063a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7064a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7065c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7066c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7067c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7068c8587f34SStefano Zampini       /* create random vec */
70692701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7070c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
70716e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7072c8587f34SStefano Zampini       /* solve coarse problem */
70736e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7074cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
70756e683305SStefano Zampini       if (compute_eigs) {
7076854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7077854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
70786e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
70791ae86dd6SStefano Zampini         if (neigs) {
70806e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
70816e683305SStefano Zampini           lambda_min = eigs_r[0];
70826e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
70832701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
70842701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7085cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7086cbcc2c2aSStefano Zampini             }
7087c8587f34SStefano Zampini           }
7088c8587f34SStefano Zampini         }
70891ae86dd6SStefano Zampini       }
7090cbcc2c2aSStefano Zampini 
7091c8587f34SStefano Zampini       /* check coarse problem residual error */
70926e683305SStefano Zampini       if (pcbddc->dbg_flag) {
70936e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
70946e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
70956e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7096c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
70976e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
70986e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7099779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
71006e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
71016e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
71026e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
71036e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7104b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7105b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7106b0f5fe93SStefano Zampini         }
71076e683305SStefano Zampini         if (compute_eigs) {
71086e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7109deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7110c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
71116e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
71126e683305SStefano 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);
71136e683305SStefano Zampini           for (i=0;i<neigs;i++) {
71146e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7115c8587f34SStefano Zampini           }
71166e683305SStefano Zampini         }
71176e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
71186e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
71196e683305SStefano Zampini       }
7120e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
71212701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7122c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
71236e683305SStefano Zampini       if (compute_eigs) {
71246e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
71256e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7126c8587f34SStefano Zampini       }
71276e683305SStefano Zampini     }
71286e683305SStefano Zampini   }
7129bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7130cbcc2c2aSStefano Zampini   /* print additional info */
7131cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
71326e683305SStefano Zampini     /* waits until all processes reaches this point */
71336e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7134cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7135cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7136cbcc2c2aSStefano Zampini   }
7137cbcc2c2aSStefano Zampini 
71382b510759SStefano Zampini   /* free memory */
7139fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7140c8587f34SStefano Zampini   PetscFunctionReturn(0);
7141c8587f34SStefano Zampini }
7142674ae819SStefano Zampini 
7143f34684f1SStefano Zampini #undef __FUNCT__
7144f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7145f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7146f34684f1SStefano Zampini {
7147f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7148f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7149f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7150dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7151dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
715273be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7153dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7154f34684f1SStefano Zampini   PetscErrorCode ierr;
7155f34684f1SStefano Zampini 
7156f34684f1SStefano Zampini   PetscFunctionBegin;
7157f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
71586c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7159dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
71603bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7161dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7162dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
71636583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7164dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7165dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7166dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
71676c4ed002SBarry 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);
7168dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7169dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7170dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7171dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7172dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7173f34684f1SStefano Zampini 
7174f34684f1SStefano Zampini   /* check numbering */
7175f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7176019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7177dc456d91SStefano Zampini     PetscInt    i;
7178b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7179f34684f1SStefano Zampini 
7180f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7181f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7182f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
71831575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7184019a44ceSStefano Zampini     /* counter */
7185019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7186019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7187019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7188019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7189019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7190019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7191f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7192f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7193727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7194f34684f1SStefano Zampini     }
7195f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7196f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7197f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7198e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7199e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7200e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7201e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7202f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7203019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7204f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7205019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
72062c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
720775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7208b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
72092c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
72102c66d082SStefano 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);
7211f34684f1SStefano Zampini       }
7212f34684f1SStefano Zampini     }
7213019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7214b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7215f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7216f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7217f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7218f34684f1SStefano Zampini     }
7219f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7220f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7221e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7222e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7223f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7224f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7225b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7226ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7227ca8b9ea9SStefano Zampini 
7228ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
72293bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7230f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7231f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7232f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7233f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
72344bc2dc4bSStefano 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);
7235f34684f1SStefano Zampini       }
7236f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7237ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7238f34684f1SStefano Zampini     }
7239f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
72401575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7241302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7242f34684f1SStefano Zampini   }
72438bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7244f34684f1SStefano Zampini   /* get back data */
7245f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7246f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7247674ae819SStefano Zampini   PetscFunctionReturn(0);
7248674ae819SStefano Zampini }
7249674ae819SStefano Zampini 
7250e456f2a8SStefano Zampini #undef __FUNCT__
7251e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7252a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7253e456f2a8SStefano Zampini {
7254e456f2a8SStefano Zampini   IS             localis_t;
7255a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7256e456f2a8SStefano Zampini   PetscScalar    *vals;
7257e456f2a8SStefano Zampini   PetscErrorCode ierr;
7258e456f2a8SStefano Zampini 
7259e456f2a8SStefano Zampini   PetscFunctionBegin;
7260a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7261e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7262854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7263e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7264e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7265a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7266a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
72671035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7268a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
72691035eff8SStefano Zampini   }
7270a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7271e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7272e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7273a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7274a7dc3881SStefano Zampini   /* now compute set in local ordering */
7275a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7276a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7277a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7278a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7279a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7280ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7281e456f2a8SStefano Zampini       lsize++;
7282e456f2a8SStefano Zampini     }
7283e456f2a8SStefano Zampini   }
7284854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7285a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7286ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7287e456f2a8SStefano Zampini       idxs[lsize++] = i;
7288e456f2a8SStefano Zampini     }
7289e456f2a8SStefano Zampini   }
7290a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7291a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7292e456f2a8SStefano Zampini   *localis = localis_t;
7293e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7294e456f2a8SStefano Zampini }
7295906d46d4SStefano Zampini 
7296b96c3477SStefano Zampini #undef __FUNCT__
7297b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
729808122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7299b96c3477SStefano Zampini {
7300a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7301b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7302b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7303a64f4aa4SStefano Zampini   Mat                 S_j;
7304b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7305b96c3477SStefano Zampini   PetscBool           free_used_adj;
7306b96c3477SStefano Zampini   PetscErrorCode      ierr;
7307b96c3477SStefano Zampini 
7308b96c3477SStefano Zampini   PetscFunctionBegin;
7309b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7310b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
731108122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7312b96c3477SStefano Zampini     used_xadj = NULL;
7313b96c3477SStefano Zampini     used_adjncy = NULL;
7314b96c3477SStefano Zampini   } else {
731508122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
731608122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
731708122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
731808122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7319b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7320b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7321b96c3477SStefano Zampini     } else {
73222fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7323b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7324b96c3477SStefano Zampini       PetscInt       nvtxs;
7325b96c3477SStefano Zampini 
73262fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
73272fffb893SStefano Zampini       if (flg_row) {
7328b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7329b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7330b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7331b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
73322fffb893SStefano Zampini       } else {
73332fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
73342fffb893SStefano Zampini         used_xadj = NULL;
73352fffb893SStefano Zampini         used_adjncy = NULL;
73362fffb893SStefano Zampini       }
73372fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7338b96c3477SStefano Zampini     }
7339b96c3477SStefano Zampini   }
7340d5574798SStefano Zampini 
7341d5574798SStefano Zampini   /* setup sub_schurs data */
7342a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7343df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7344df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7345a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
734691af6908SStefano 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);
7347a64f4aa4SStefano Zampini   } else {
73486816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
73494d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7350a3df083aSStefano Zampini     PetscInt  benign_n;
735172b8c272SStefano Zampini     Mat       change = NULL;
73529d54b7f4SStefano Zampini     Vec       scaling = NULL;
735372b8c272SStefano Zampini     IS        change_primal = NULL;
7354a3df083aSStefano Zampini 
73555feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
73565feab87aSStefano Zampini       PetscInt n_vertices;
73575feab87aSStefano Zampini 
73585feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
73592034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
73605feab87aSStefano Zampini     }
736104708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
736204708bb6SStefano Zampini     if (!isseqaij) {
736304708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
736404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
736504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
736604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
736704708bb6SStefano Zampini       } else {
7368511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
736904708bb6SStefano Zampini       }
737004708bb6SStefano Zampini     }
7371a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7372a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7373ca92afb2SStefano Zampini     } else {
7374a3df083aSStefano Zampini       benign_n = 0;
7375ca92afb2SStefano Zampini     }
7376b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7377b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7378b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
737972b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
738022db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7381b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
738222db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7383b7ab4a40SStefano Zampini     }
7384b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7385b7ab4a40SStefano 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 */
7386b7ab4a40SStefano Zampini     if (need_change) {
738788c03ad3SStefano Zampini       PC_IS   *pcisf;
738888c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
738988c03ad3SStefano Zampini       PC      pcf;
739088c03ad3SStefano Zampini 
7391e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
739288c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
739388c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
739488c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
739588c03ad3SStefano Zampini       /* hacks */
739688c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
739772b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
739872b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
739972b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
740072b8c272SStefano Zampini       pcisf->n = pcis->n;
740172b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
740288c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
740388c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
740488c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
740588c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
740688c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
740788c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
740872b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
740988c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
741088c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
741172b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
741272b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
741372b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
741472b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
741572b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
741688c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
741772b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
741888c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
741988c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
742088c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
742188c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
742288c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
742388c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
742488c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
742588c03ad3SStefano Zampini     }
74269d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
742791af6908SStefano 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);
742872b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
742972b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7430ca92afb2SStefano Zampini   }
7431d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7432b96c3477SStefano Zampini 
7433b96c3477SStefano Zampini   /* free adjacency */
7434b96c3477SStefano Zampini   if (free_used_adj) {
7435b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7436b96c3477SStefano Zampini   }
7437b96c3477SStefano Zampini   PetscFunctionReturn(0);
7438b96c3477SStefano Zampini }
7439b96c3477SStefano Zampini 
7440b96c3477SStefano Zampini #undef __FUNCT__
7441b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
744208122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7443b96c3477SStefano Zampini {
7444b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7445b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7446b96c3477SStefano Zampini   PCBDDCGraph         graph;
7447b96c3477SStefano Zampini   PetscErrorCode      ierr;
7448b96c3477SStefano Zampini 
7449b96c3477SStefano Zampini   PetscFunctionBegin;
7450b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
745108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
74523301b35fSStefano Zampini     IS       verticesIS,verticescomm;
74533301b35fSStefano Zampini     PetscInt vsize,*idxs;
7454b96c3477SStefano Zampini 
7455b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
74563301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
74573301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
74583301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
74593301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7460c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7461b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7462*be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7463441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
74643301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7465b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7466b96c3477SStefano Zampini   } else {
7467b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7468b96c3477SStefano Zampini   }
7469e4d548c7SStefano Zampini   /* print some info */
7470e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7471e4d548c7SStefano Zampini     IS       vertices;
7472e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7473c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7474e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7475e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7476e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7477e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7478e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7479e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7480e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7481e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7482e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7483c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7484e4d548c7SStefano Zampini   }
7485b96c3477SStefano Zampini 
7486b96c3477SStefano Zampini   /* sub_schurs init */
7487b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7488b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7489b334f244SStefano Zampini   }
7490b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7491a64f4aa4SStefano Zampini 
7492b96c3477SStefano Zampini   /* free graph struct */
749308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7494b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7495b96c3477SStefano Zampini   }
7496b96c3477SStefano Zampini   PetscFunctionReturn(0);
7497b96c3477SStefano Zampini }
7498fa34dd3eSStefano Zampini 
7499fa34dd3eSStefano Zampini #undef __FUNCT__
7500fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7501fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7502fa34dd3eSStefano Zampini {
7503fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7504fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7505fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7506fa34dd3eSStefano Zampini 
7507fa34dd3eSStefano Zampini   PetscFunctionBegin;
7508fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7509fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
75104f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7511fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
75124f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
751375c01103SStefano Zampini     PetscReal      norm;
7514fa34dd3eSStefano Zampini     PetscInt       i;
7515fa34dd3eSStefano Zampini 
7516fa34dd3eSStefano Zampini     /* B0 and B0_B */
7517fa34dd3eSStefano Zampini     if (zerodiag) {
7518fa34dd3eSStefano Zampini       IS       dummy;
7519fa34dd3eSStefano Zampini 
75204f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
75214f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7522fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7523fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7524fa34dd3eSStefano Zampini     }
7525fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7526fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7527fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7528fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7529fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7530fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7531fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7532fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7533fa34dd3eSStefano Zampini     /* S_j */
7534fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7535fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7536fa34dd3eSStefano Zampini 
7537fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7538fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7539fa34dd3eSStefano Zampini     /* continuous in primal space */
7540fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7541fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7542fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7543fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
75444f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
75454f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7546fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7547fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7548fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7549fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7550fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7551fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7552fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7553fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7554fa34dd3eSStefano Zampini 
7555fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7556fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7557fa34dd3eSStefano Zampini     /* local with Schur */
7558fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7559fa34dd3eSStefano Zampini     if (zerodiag) {
7560fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
75614f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7562fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7563fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7564fa34dd3eSStefano Zampini     }
7565fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7566fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7567fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7568fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7569fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7570fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7571fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7572fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7573fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7574fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7575fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7576fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7577fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7578fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7579fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7580fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7581fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7582fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7583fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7584fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7585fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7586fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7587fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7588fa34dd3eSStefano Zampini     if (zerodiag) {
7589fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7590fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
75914f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7592fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7593fa34dd3eSStefano Zampini     }
7594fa34dd3eSStefano Zampini     /* BDDC */
7595fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7596fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7597fa34dd3eSStefano Zampini 
7598fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7599fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7600fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7601fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
76024f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
76034f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7604fa34dd3eSStefano Zampini     }
76054f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7606fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7607fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7608fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7609fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7610fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7611fa34dd3eSStefano Zampini   }
7612fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7613fa34dd3eSStefano Zampini }
7614