xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision d904f53ba2765a953cf2046c2cc05015002d089d)
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;
1104e64d54eSstefano_zampini   Mat                    G,T,conn,lG,lGt,lGis,lGall,lGe;
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;
1184e64d54eSstefano_zampini   PetscBT                btv,bte,btvc,btb,btvcand,btvi;
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               i,j,extmem,cum,maxsize,rst,nee,nquads=2;
125a13144ffSStefano Zampini   PetscInt               *extrow,*extrowcum,*marks,*emarks,*vmarks,*gidxs;
126a13144ffSStefano Zampini   PetscInt               *sfvleaves,*sfvroots;
127a13144ffSStefano Zampini   PetscBool              print,eerr,done,lrc[2],conforming,ismpiaij;
128a13144ffSStefano Zampini   PetscErrorCode         ierr;
129a13144ffSStefano Zampini 
130a13144ffSStefano Zampini   PetscFunctionBegin;
131a13144ffSStefano Zampini   /* test variable order code and print debug info TODO: to be removed */
132a13144ffSStefano Zampini   print = PETSC_FALSE;
133a13144ffSStefano Zampini   ierr = PetscOptionsGetBool(NULL,NULL,"-pc_bddc_print_nedelec",&print,NULL);CHKERRQ(ierr);
134a13144ffSStefano Zampini   ierr = PetscOptionsGetInt(NULL,NULL,"-pc_bddc_nedelec_order",&pcbddc->nedorder,NULL);CHKERRQ(ierr);
135a13144ffSStefano Zampini 
136a13144ffSStefano Zampini   /* Return to caller if there are no edges in the decomposition */
137a13144ffSStefano Zampini   ierr   = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
138a13144ffSStefano Zampini   ierr   = MatGetLocalToGlobalMapping(pc->pmat,&el2g,NULL);CHKERRQ(ierr);
139a13144ffSStefano Zampini   ierr   = ISLocalToGlobalMappingGetSize(el2g,&ne);CHKERRQ(ierr);
140a13144ffSStefano Zampini   ierr   = VecGetArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
141a13144ffSStefano Zampini   lrc[0] = PETSC_FALSE;
142a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
143a13144ffSStefano Zampini     if (PetscRealPart(vals[i]) > 2.) {
144a13144ffSStefano Zampini       lrc[0] = PETSC_TRUE;
145a13144ffSStefano Zampini       break;
146a13144ffSStefano Zampini     }
147a13144ffSStefano Zampini   }
148a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals);CHKERRQ(ierr);
149a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
150a13144ffSStefano Zampini   if (!lrc[1]) PetscFunctionReturn(0);
151a13144ffSStefano Zampini 
152a13144ffSStefano Zampini   /* Get relevant objects */
153a13144ffSStefano Zampini   G          = pcbddc->discretegradient;
154a13144ffSStefano Zampini   order      = pcbddc->nedorder;
155a13144ffSStefano Zampini   conforming = pcbddc->conforming;
156a13144ffSStefano Zampini 
157a13144ffSStefano Zampini   /* Compute local and global sizes of egde dofs and nodal dofs */
158a13144ffSStefano Zampini   ierr = MatGetSize(G,&Ne,&Nv);CHKERRQ(ierr);
159a13144ffSStefano Zampini   ierr = MatGetLocalSize(G,&Le,&Lv);CHKERRQ(ierr);
160a13144ffSStefano Zampini 
161a13144ffSStefano Zampini   /* Sanity checks */
162a13144ffSStefano Zampini   if (!order && !conforming) SETERRQ(comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time");
163a13144ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)G,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
164a13144ffSStefano 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);
165a13144ffSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) SETERRQ(comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis");
166a13144ffSStefano 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);
167a13144ffSStefano 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);
168a13144ffSStefano Zampini   ierr = MatGetSize(pc->pmat,&i,NULL);CHKERRQ(ierr);
169a13144ffSStefano 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);
170a13144ffSStefano Zampini   ierr = MatGetLocalSize(pc->pmat,&i,NULL);CHKERRQ(ierr);
171a13144ffSStefano 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);
172a13144ffSStefano Zampini 
173a13144ffSStefano Zampini   /* Drop connections for interior edges (this modifies G) */
174a13144ffSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&tvec,NULL);CHKERRQ(ierr);
175a13144ffSStefano Zampini   ierr = VecScatterBegin(matis->rctx,matis->counter,tvec,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
176a13144ffSStefano Zampini   ierr = VecScatterEnd(matis->rctx,matis->counter,tvec,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
177a13144ffSStefano Zampini   ierr = PetscMalloc1(Le,&marks);CHKERRQ(ierr);
178a13144ffSStefano Zampini   ierr = VecGetOwnershipRange(tvec,&rst,NULL);CHKERRQ(ierr);
179a13144ffSStefano Zampini   ierr = VecGetArrayRead(tvec,(const PetscScalar**)&vals);CHKERRQ(ierr);
180a13144ffSStefano Zampini   cum  = 0;
181a13144ffSStefano Zampini   for (i=0;i<Le;i++) if (PetscRealPart(vals[i]) < 1.5) marks[cum++] = i+rst;
182a13144ffSStefano Zampini   ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&vals);CHKERRQ(ierr);
183a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE);CHKERRQ(ierr);
184a13144ffSStefano Zampini   ierr = MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
185a13144ffSStefano Zampini   ierr = MatZeroRows(G,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
186a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
187a13144ffSStefano Zampini 
188a13144ffSStefano Zampini   /* Extract subdomain relevant rows of G */
189a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(el2g,&idxs);CHKERRQ(ierr);
190a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned);CHKERRQ(ierr);
191a13144ffSStefano Zampini   ierr = MatGetSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall);CHKERRQ(ierr);
192a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(el2g,&idxs);CHKERRQ(ierr);
193a13144ffSStefano Zampini   ierr = ISDestroy(&lned);CHKERRQ(ierr);
194a13144ffSStefano Zampini   ierr = MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis);CHKERRQ(ierr);
195a13144ffSStefano Zampini   ierr = MatDestroy(&lGall);CHKERRQ(ierr);
196a13144ffSStefano Zampini   ierr = MatISGetLocalMat(lGis,&lG);CHKERRQ(ierr);
197a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)lG);CHKERRQ(ierr);
198a13144ffSStefano Zampini   if (print) {
199a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"initial_lG");CHKERRQ(ierr);
200a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
201a13144ffSStefano Zampini   }
202a13144ffSStefano Zampini 
203a13144ffSStefano Zampini   /* SF for nodal communications */
204a13144ffSStefano Zampini   ierr = MatGetLocalToGlobalMapping(lGis,NULL,&vl2g);CHKERRQ(ierr);
205a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)vl2g);CHKERRQ(ierr);
206a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(vl2g,&nv);CHKERRQ(ierr);
207a13144ffSStefano Zampini   ierr = PetscSFCreate(comm,&sfv);CHKERRQ(ierr);
208a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(vl2g,&idxs);CHKERRQ(ierr);
209a13144ffSStefano Zampini   ierr = PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs);CHKERRQ(ierr);
210a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs);CHKERRQ(ierr);
211a13144ffSStefano Zampini   ierr = PetscMalloc2(nv,&sfvleaves,Lv,&sfvroots);CHKERRQ(ierr);
212a13144ffSStefano Zampini 
213a13144ffSStefano Zampini   /* Destroy temporary G created in MATIS format */
214a13144ffSStefano Zampini   ierr = MatDestroy(&lGis);CHKERRQ(ierr);
215a13144ffSStefano Zampini 
216a13144ffSStefano Zampini   /* Analyze the edge-nodes connections (duplicate lG) */
2174e64d54eSstefano_zampini   ierr = MatDuplicate(lG,MAT_COPY_VALUES,&lGe);CHKERRQ(ierr);
2184e64d54eSstefano_zampini   ierr = MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
219a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btv);CHKERRQ(ierr);
220a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&bte);CHKERRQ(ierr);
221a13144ffSStefano Zampini   ierr = PetscBTCreate(ne,&btb);CHKERRQ(ierr);
222a13144ffSStefano Zampini   /* need to import the boundary specification to ensure the
223a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
224a13144ffSStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
225a13144ffSStefano Zampini     ierr = ISGetLocalSize(pcbddc->DirichletBoundariesLocal,&cum);CHKERRQ(ierr);
226a13144ffSStefano Zampini     ierr = ISGetIndices(pcbddc->DirichletBoundariesLocal,&idxs);CHKERRQ(ierr);
227a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
228a13144ffSStefano Zampini       if (idxs[i] >= 0) {
229a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
230a13144ffSStefano Zampini       }
231a13144ffSStefano Zampini     }
232a13144ffSStefano Zampini     ierr = ISRestoreIndices(pcbddc->DirichletBoundariesLocal,&idxs);CHKERRQ(ierr);
233a13144ffSStefano Zampini   }
234a13144ffSStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
235a13144ffSStefano Zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&cum);CHKERRQ(ierr);
236a13144ffSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
237a13144ffSStefano Zampini     for (i=0;i<cum;i++) {
238a13144ffSStefano Zampini       if (idxs[i] >= 0) {
239a13144ffSStefano Zampini         ierr = PetscBTSet(btb,idxs[i]);CHKERRQ(ierr);
240a13144ffSStefano Zampini       }
241a13144ffSStefano Zampini     }
242a13144ffSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
243a13144ffSStefano Zampini   }
244a13144ffSStefano Zampini   ierr = PetscBTCreate(nv,&btvcand);CHKERRQ(ierr);
245a13144ffSStefano Zampini   /* need to remove coarse faces' dofs to ensure the
246a13144ffSStefano Zampini      proper detection of coarse edges' endpoints */
247a13144ffSStefano Zampini   ierr = PetscCalloc1(ne,&marks);CHKERRQ(ierr);
248a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
249a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
250a13144ffSStefano Zampini     PetscInt j;
251a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) marks[shared[i][j]]++;
252a13144ffSStefano Zampini   }
253a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(el2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
254a13144ffSStefano Zampini   cum  = 0;
2554e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
256dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGe,&vals);CHKERRQ(ierr);
257a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
258dec27d64SStefano Zampini     /* eliminate rows corresponding to edge dofs belonging to coarse faces */
259dec27d64SStefano Zampini     if (!marks[i] || (marks[i] == 1 && !PetscBTLookup(btb,i))) {
260a13144ffSStefano Zampini       marks[cum++] = i;
261dec27d64SStefano Zampini       continue;
262dec27d64SStefano Zampini     }
263dec27d64SStefano Zampini     /* set badly connected edge dofs as primal */
264dec27d64SStefano Zampini     if (!conforming && ii[i+1]-ii[i] != order + 1) {
265a13144ffSStefano Zampini       marks[cum++] = i;
266a13144ffSStefano Zampini       ierr = PetscBTSet(bte,i);CHKERRQ(ierr);
267a13144ffSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
268a13144ffSStefano Zampini         ierr = PetscBTSet(btv,jj[j]);CHKERRQ(ierr);
269a13144ffSStefano Zampini       }
270a13144ffSStefano Zampini     }
271dec27d64SStefano Zampini     /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */
272dec27d64SStefano Zampini     if (!order && ii[i+1] != ii[i]) {
273dec27d64SStefano Zampini       PetscScalar val = 1./(ii[i+1]-ii[i]-1);
274dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vals[j] = val;
275a13144ffSStefano Zampini     }
276dec27d64SStefano Zampini   }
277dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGe,&vals);CHKERRQ(ierr);
2784e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
2794e64d54eSstefano_zampini   ierr = MatZeroRows(lGe,cum,marks,0.,NULL,NULL);CHKERRQ(ierr);
280a13144ffSStefano Zampini   /* identify splitpoints and corner candidates: TODO variable order */
2814e64d54eSstefano_zampini   ierr = MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
282a13144ffSStefano Zampini   if (print) {
2834e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGe,"edgerestr_lG");CHKERRQ(ierr);
2844e64d54eSstefano_zampini     ierr = MatView(lGe,NULL);CHKERRQ(ierr);
2854e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt");CHKERRQ(ierr);
286a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
287a13144ffSStefano Zampini   }
288a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
289dec27d64SStefano Zampini   ierr = MatSeqAIJGetArray(lGt,&vals);CHKERRQ(ierr);
290a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
291dec27d64SStefano Zampini     PetscInt ord = order, test = ii[i+1]-ii[i];
292dec27d64SStefano Zampini     if (!order) {
293dec27d64SStefano Zampini       PetscReal vorder = 0.;
294dec27d64SStefano Zampini 
295dec27d64SStefano Zampini       for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]);
296dec27d64SStefano Zampini       test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON);
297dec27d64SStefano Zampini       if (vorder-test > PETSC_SQRT_MACHINE_EPSILON) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%d)",vorder,test);
298dec27d64SStefano Zampini       ord  = 1;
299dec27d64SStefano Zampini     }
300a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
301dec27d64SStefano Zampini     if (test%ord) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %d connected with nodal dof %d with order %d",test,i,ord);
302a13144ffSStefano Zampini #endif
303dec27d64SStefano Zampini     if (test >= 3*ord) { /* splitpoints */
304a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %d\n",i);
305a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
306dec27d64SStefano Zampini     } else if (test == ord) {
307a13144ffSStefano Zampini       if (order == 1) {
308a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %d\n",i);
309a13144ffSStefano Zampini         ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
310a13144ffSStefano Zampini       } else {
311a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %d\n",i);
312a13144ffSStefano Zampini         ierr = PetscBTSet(btvcand,i);CHKERRQ(ierr);
313a13144ffSStefano Zampini       }
314a13144ffSStefano Zampini     }
315a13144ffSStefano Zampini   }
316dec27d64SStefano Zampini   ierr = MatSeqAIJRestoreArray(lGt,&vals);CHKERRQ(ierr);
317a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
318a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
319a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btb);CHKERRQ(ierr);
320a13144ffSStefano Zampini 
321a13144ffSStefano Zampini   /* Get the local G^T explicitly */
322a13144ffSStefano Zampini   ierr = MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt);CHKERRQ(ierr);
3234e64d54eSstefano_zampini   ierr = MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE);CHKERRQ(ierr);
324a13144ffSStefano Zampini   if (print) {
325a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"initial_lGt");CHKERRQ(ierr);
326a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
327a13144ffSStefano Zampini   }
328a13144ffSStefano Zampini 
3294e64d54eSstefano_zampini   /* Mark interior nodal dofs */
330a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
3314e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvi);CHKERRQ(ierr);
332a13144ffSStefano Zampini   for (i=1;i<n_neigh;i++) {
333a13144ffSStefano Zampini     for (j=0;j<n_shared[i];j++) {
3344e64d54eSstefano_zampini       ierr = PetscBTSet(btvi,shared[i][j]);CHKERRQ(ierr);
335a13144ffSStefano Zampini     }
336a13144ffSStefano Zampini   }
337a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
338a13144ffSStefano Zampini 
339a13144ffSStefano Zampini   /* communicate corners and splitpoints */
340a13144ffSStefano Zampini   ierr = PetscMalloc1(nv,&vmarks);CHKERRQ(ierr);
341a13144ffSStefano Zampini   ierr = PetscMemzero(sfvleaves,nv*sizeof(PetscInt));CHKERRQ(ierr);
342a13144ffSStefano Zampini   ierr = PetscMemzero(sfvroots,Lv*sizeof(PetscInt));CHKERRQ(ierr);
343a13144ffSStefano Zampini   for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1;
344a13144ffSStefano Zampini 
345a13144ffSStefano Zampini   if (print) {
346a13144ffSStefano Zampini     IS tbz;
347a13144ffSStefano Zampini 
348a13144ffSStefano Zampini     cum = 0;
349a13144ffSStefano Zampini     for (i=0;i<nv;i++)
350a13144ffSStefano Zampini       if (sfvleaves[i])
351a13144ffSStefano Zampini         vmarks[cum++] = i;
352a13144ffSStefano Zampini 
353a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
354a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local");CHKERRQ(ierr);
355a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
356a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
357a13144ffSStefano Zampini   }
358a13144ffSStefano Zampini 
359a13144ffSStefano Zampini   ierr = PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
360a13144ffSStefano Zampini   ierr = PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM);CHKERRQ(ierr);
361a13144ffSStefano Zampini   ierr = PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
362a13144ffSStefano Zampini   ierr = PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves);CHKERRQ(ierr);
363a13144ffSStefano Zampini 
3644e64d54eSstefano_zampini   /* Zero rows of lGt corresponding to identified corners
3654e64d54eSstefano_zampini      and interior nodal dofs */
366a13144ffSStefano Zampini   cum = 0;
367a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
368a13144ffSStefano Zampini     if (sfvleaves[i]) {
369a13144ffSStefano Zampini       vmarks[cum++] = i;
370a13144ffSStefano Zampini       ierr = PetscBTSet(btv,i);CHKERRQ(ierr);
371a13144ffSStefano Zampini     }
3724e64d54eSstefano_zampini     if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i;
373a13144ffSStefano Zampini   }
3744e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvi);CHKERRQ(ierr);
375a13144ffSStefano Zampini   if (print) {
376a13144ffSStefano Zampini     IS tbz;
377a13144ffSStefano Zampini 
378a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz);CHKERRQ(ierr);
3794e64d54eSstefano_zampini     ierr = PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior");CHKERRQ(ierr);
380a13144ffSStefano Zampini     ierr = ISView(tbz,NULL);CHKERRQ(ierr);
381a13144ffSStefano Zampini     ierr = ISDestroy(&tbz);CHKERRQ(ierr);
382a13144ffSStefano Zampini   }
383a13144ffSStefano Zampini   ierr = MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL);CHKERRQ(ierr);
384a13144ffSStefano Zampini   ierr = PetscFree(vmarks);CHKERRQ(ierr);
385a13144ffSStefano Zampini   ierr = PetscSFDestroy(&sfv);CHKERRQ(ierr);
386a13144ffSStefano Zampini   ierr = PetscFree2(sfvleaves,sfvroots);CHKERRQ(ierr);
387a13144ffSStefano Zampini 
388a13144ffSStefano Zampini   /* Recompute G */
389a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
390a13144ffSStefano Zampini   ierr = MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG);CHKERRQ(ierr);
391a13144ffSStefano Zampini   if (print) {
392a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lG,"used_lG");CHKERRQ(ierr);
393a13144ffSStefano Zampini     ierr = MatView(lG,NULL);CHKERRQ(ierr);
394a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)lGt,"used_lGt");CHKERRQ(ierr);
395a13144ffSStefano Zampini     ierr = MatView(lGt,NULL);CHKERRQ(ierr);
396a13144ffSStefano Zampini   }
397a13144ffSStefano Zampini 
398a13144ffSStefano Zampini   /* Get primal dofs (if any) */
399a13144ffSStefano Zampini   cum = 0;
400a13144ffSStefano Zampini   for (i=0;i<ne;i++) {
401a13144ffSStefano Zampini     if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i;
402a13144ffSStefano Zampini   }
403a13144ffSStefano Zampini   ierr = ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
404a13144ffSStefano Zampini   if (print) {
405a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs");CHKERRQ(ierr);
406a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
407a13144ffSStefano Zampini   }
408a13144ffSStefano Zampini   ierr = PetscBTDestroy(&bte);CHKERRQ(ierr);
409a13144ffSStefano Zampini   ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
410a13144ffSStefano Zampini   ierr = ISDestroy(&primals);CHKERRQ(ierr);
411a13144ffSStefano Zampini 
412a13144ffSStefano Zampini   /* Compute edge connectivity */
413a13144ffSStefano Zampini   ierr = PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_");CHKERRQ(ierr);
414a13144ffSStefano Zampini   ierr = MatMatMultSymbolic(lG,lGt,PETSC_DEFAULT,&conn);CHKERRQ(ierr);
415a13144ffSStefano Zampini   ierr = MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
416*d904f53bSStefano Zampini   if (done && i && ii && jj) { /* when lG is empty, don't pass pointers */
417a13144ffSStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,ne,ii,jj,PETSC_USE_POINTER);CHKERRQ(ierr);
418*d904f53bSStefano Zampini   }
419a13144ffSStefano Zampini   /* Analyze interface for edge dofs */
420a13144ffSStefano Zampini   ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
421a13144ffSStefano Zampini   if (print) { ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); }
422a13144ffSStefano Zampini 
423a13144ffSStefano Zampini   /* Get coarse edges in the edge space */
424a13144ffSStefano Zampini   pcbddc->mat_graph->twodim = PETSC_FALSE;
425a13144ffSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
426a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
427a13144ffSStefano Zampini 
428a13144ffSStefano Zampini   /* Mark fine edge dofs with their coarse edge id */
429a13144ffSStefano Zampini   maxsize = 0;
430a13144ffSStefano Zampini   ierr    = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
431a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
432a13144ffSStefano Zampini     PetscInt size,mark = i+1;
433a13144ffSStefano Zampini 
434a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
435a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
436a13144ffSStefano Zampini     for (j=0;j<size;j++) marks[idxs[j]] = mark;
437a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
438a13144ffSStefano Zampini     maxsize = PetscMax(maxsize,size);
439a13144ffSStefano Zampini   }
440a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
441a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
442a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = nee+1;
443a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
444a13144ffSStefano Zampini   if (print) {
445a13144ffSStefano Zampini     ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs");CHKERRQ(ierr);
446a13144ffSStefano Zampini     ierr = ISView(primals,NULL);CHKERRQ(ierr);
447a13144ffSStefano Zampini   }
448a13144ffSStefano Zampini 
449a13144ffSStefano Zampini   /* Find coarse edge endpoints */
450a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
451a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
452a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
453a13144ffSStefano Zampini     PetscInt mark = i+1,size;
454a13144ffSStefano Zampini 
455a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
456a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
457a13144ffSStefano Zampini     if (print) {
458a13144ffSStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %d\n",i);
459a13144ffSStefano Zampini       ISView(eedges[i],NULL);
460a13144ffSStefano Zampini     }
461a13144ffSStefano Zampini     for (j=0;j<size;j++) {
462a13144ffSStefano Zampini       PetscInt k, ee = idxs[j];
463a13144ffSStefano Zampini       if (print) PetscPrintf(PETSC_COMM_SELF,"  idx %d\n",ee);
464a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) {
465a13144ffSStefano Zampini         if (print) PetscPrintf(PETSC_COMM_SELF,"    inspect %d\n",jj[k]);
466a13144ffSStefano Zampini         if (PetscBTLookup(btv,jj[k])) {
467a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      corner found (already set) %d\n",jj[k]);
468a13144ffSStefano Zampini         } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */
469a13144ffSStefano Zampini           if (print) PetscPrintf(PETSC_COMM_SELF,"      candidate? %d\n",(PetscBool)(PetscBTLookup(btvcand,jj[k])));
470a13144ffSStefano Zampini           PetscInt  k2;
471a13144ffSStefano Zampini           PetscBool corner = PETSC_FALSE;
472a13144ffSStefano Zampini           for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) {
473a13144ffSStefano 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]]);
474a13144ffSStefano Zampini             if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) ||
475a13144ffSStefano Zampini                 pcbddc->mat_graph->special_dof[jjt[k2]] == PCBDDCGRAPH_DIRICHLET_MARK) {
476a13144ffSStefano Zampini               corner = PETSC_TRUE;
477a13144ffSStefano Zampini               break;
478a13144ffSStefano Zampini             }
479a13144ffSStefano Zampini           }
480a13144ffSStefano Zampini           if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */
481a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        corner found %d\n",jj[k]);
482a13144ffSStefano Zampini             ierr = PetscBTSet(btv,jj[k]);CHKERRQ(ierr);
483a13144ffSStefano Zampini           } else {
484a13144ffSStefano Zampini             if (print) PetscPrintf(PETSC_COMM_SELF,"        no corners found\n");
485a13144ffSStefano Zampini           }
486a13144ffSStefano Zampini         }
487a13144ffSStefano Zampini       }
488a13144ffSStefano Zampini     }
489a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
490a13144ffSStefano Zampini   }
491a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
492a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
493a13144ffSStefano Zampini 
494a13144ffSStefano Zampini   /* Reset marked primal dofs */
495a13144ffSStefano Zampini   ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
496a13144ffSStefano Zampini   ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
497a13144ffSStefano Zampini   for (i=0;i<cum;i++) marks[idxs[i]] = 0;
498a13144ffSStefano Zampini   ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
499a13144ffSStefano Zampini 
500a13144ffSStefano Zampini   /* Compute extended cols indices */
501a13144ffSStefano Zampini   ierr = MatGetRowIJ(lG ,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
502a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
503a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lG,&i);CHKERRQ(ierr);
504a13144ffSStefano Zampini   i   *= maxsize;
505a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extcols);CHKERRQ(ierr);
506a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&emarks);CHKERRQ(ierr);
507a13144ffSStefano Zampini   ierr = PetscMalloc2(i,&extrow,i,&gidxs);CHKERRQ(ierr);
508a13144ffSStefano Zampini   eerr = PETSC_FALSE;
509a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
510a13144ffSStefano Zampini     PetscInt size;
511a13144ffSStefano Zampini 
512a13144ffSStefano Zampini     cum  = 0;
513a13144ffSStefano Zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
514a13144ffSStefano Zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
515a13144ffSStefano Zampini     for (j=0;j<size;j++) {
516a13144ffSStefano Zampini       PetscInt k,ee = idxs[j];
517a13144ffSStefano Zampini       for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k];
518a13144ffSStefano Zampini     }
519a13144ffSStefano Zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
520a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
521a13144ffSStefano Zampini     ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
522a13144ffSStefano Zampini     ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
523a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
524a13144ffSStefano Zampini     /* it may happen that endpoints are not defined at this point
525a13144ffSStefano Zampini        if it is the case, mark this edge for a second pass */
526a13144ffSStefano Zampini     if (cum != size -1) {
527a13144ffSStefano Zampini       emarks[i] = 1;
528a13144ffSStefano Zampini       if (print) {
529a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge");CHKERRQ(ierr);
530a13144ffSStefano Zampini         ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
531a13144ffSStefano Zampini         ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol");CHKERRQ(ierr);
532a13144ffSStefano Zampini         ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
533a13144ffSStefano Zampini       }
534a13144ffSStefano Zampini       eerr = PETSC_TRUE;
535a13144ffSStefano Zampini     }
536a13144ffSStefano Zampini   }
5374e64d54eSstefano_zampini   /* if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */
538a13144ffSStefano Zampini   ierr = MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm);CHKERRQ(ierr);
539a13144ffSStefano Zampini   if (done) {
540a13144ffSStefano Zampini     PetscInt *newprimals;
541a13144ffSStefano Zampini 
542a13144ffSStefano Zampini     ierr = PetscMalloc1(ne,&newprimals);CHKERRQ(ierr);
543a13144ffSStefano Zampini     ierr = ISGetLocalSize(primals,&cum);CHKERRQ(ierr);
544a13144ffSStefano Zampini     ierr = ISGetIndices(primals,&idxs);CHKERRQ(ierr);
545a13144ffSStefano Zampini     ierr = PetscMemcpy(newprimals,idxs,cum*sizeof(PetscInt));CHKERRQ(ierr);
546a13144ffSStefano Zampini     ierr = ISRestoreIndices(primals,&idxs);CHKERRQ(ierr);
547a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
548a13144ffSStefano Zampini       if (emarks[i]) {
549a13144ffSStefano Zampini         PetscInt size,mark = i+1;
550a13144ffSStefano Zampini 
551a13144ffSStefano Zampini         ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
552a13144ffSStefano Zampini         ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
553a13144ffSStefano Zampini         for (j=0;j<size;j++) {
5544e64d54eSstefano_zampini           /* newprimals[cum++] = idxs[j]; */
555a13144ffSStefano Zampini           PetscInt k,ee = idxs[j];
556a13144ffSStefano Zampini           for (k=ii[ee];k<ii[ee+1];k++) {
557a13144ffSStefano Zampini             /* set all candidates located on the edge as corners */
558a13144ffSStefano Zampini             if (PetscBTLookup(btvcand,jj[k])) {
559a13144ffSStefano Zampini               PetscInt k2,vv = jj[k];
560a13144ffSStefano Zampini               ierr = PetscBTSet(btv,vv);CHKERRQ(ierr);
561a13144ffSStefano Zampini               /* set all edge dofs connected to candidate as primals */
562a13144ffSStefano Zampini               for (k2=iit[vv];k2<iit[vv+1];k2++) {
563a13144ffSStefano Zampini                 if (marks[jjt[k2]] == mark) {
564a13144ffSStefano Zampini                   PetscInt k3,ee2 = jjt[k2];
565a13144ffSStefano Zampini                   newprimals[cum++] = ee2;
566a13144ffSStefano Zampini                   /* finally set the new corners */
567a13144ffSStefano Zampini                   for (k3=ii[ee2];k3<ii[ee2+1];k3++) {
568a13144ffSStefano Zampini                     ierr = PetscBTSet(btv,jj[k3]);CHKERRQ(ierr);
569a13144ffSStefano Zampini                   }
570a13144ffSStefano Zampini                 }
571a13144ffSStefano Zampini               }
572a13144ffSStefano Zampini             }
573a13144ffSStefano Zampini           }
574a13144ffSStefano Zampini         }
575a13144ffSStefano Zampini         ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
576a13144ffSStefano Zampini       }
577a13144ffSStefano Zampini       ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
578a13144ffSStefano Zampini     }
579a13144ffSStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
580a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&cum,newprimals);CHKERRQ(ierr);
581a13144ffSStefano Zampini     ierr = ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals);CHKERRQ(ierr);
582a13144ffSStefano Zampini     ierr = PetscFree(newprimals);CHKERRQ(ierr);
583a13144ffSStefano Zampini     ierr = PCBDDCSetPrimalVerticesLocalIS(pc,primals);CHKERRQ(ierr);
584a13144ffSStefano Zampini     ierr = ISDestroy(&primals);CHKERRQ(ierr);
585a13144ffSStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
586a13144ffSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
587a13144ffSStefano Zampini 
588a13144ffSStefano Zampini     /* Mark again */
589a13144ffSStefano Zampini     ierr = PetscMemzero(marks,ne*sizeof(PetscInt));CHKERRQ(ierr);
590a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
591a13144ffSStefano Zampini       PetscInt size,mark = i+1;
592a13144ffSStefano Zampini 
593a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
594a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
595a13144ffSStefano Zampini       for (j=0;j<size;j++) marks[idxs[j]] = mark;
596a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
597a13144ffSStefano Zampini     }
598a13144ffSStefano Zampini     if (print) {
599a13144ffSStefano Zampini       ierr = PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass");CHKERRQ(ierr);
600a13144ffSStefano Zampini       ierr = ISView(primals,NULL);CHKERRQ(ierr);
601a13144ffSStefano Zampini     }
602a13144ffSStefano Zampini 
603a13144ffSStefano Zampini     /* Recompute extended cols */
604a13144ffSStefano Zampini     eerr = PETSC_FALSE;
605a13144ffSStefano Zampini     for (i=0;i<nee;i++) {
606a13144ffSStefano Zampini       PetscInt size;
607a13144ffSStefano Zampini 
608a13144ffSStefano Zampini       cum  = 0;
609a13144ffSStefano Zampini       ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
610a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
611a13144ffSStefano Zampini       for (j=0;j<size;j++) {
612a13144ffSStefano Zampini         PetscInt k,ee = idxs[j];
613a13144ffSStefano Zampini         for (k=ii[ee];k<ii[ee+1];k++) {
614a13144ffSStefano Zampini           if (!PetscBTLookup(btv,jj[k])) {
615a13144ffSStefano Zampini             extrow[cum++] = jj[k];
616a13144ffSStefano Zampini           }
617a13144ffSStefano Zampini         }
618a13144ffSStefano Zampini       }
619a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
620a13144ffSStefano Zampini       ierr = PetscSortRemoveDupsInt(&cum,extrow);CHKERRQ(ierr);
621a13144ffSStefano Zampini       ierr = ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs);CHKERRQ(ierr);
622a13144ffSStefano Zampini       ierr = PetscSortIntWithArray(cum,gidxs,extrow);CHKERRQ(ierr);
623a13144ffSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i]);CHKERRQ(ierr);
624a13144ffSStefano Zampini       if (cum != size -1) {
625a13144ffSStefano Zampini         if (print) {
626a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass");CHKERRQ(ierr);
627a13144ffSStefano Zampini           ierr = ISView(eedges[i],NULL);CHKERRQ(ierr);
628a13144ffSStefano Zampini           ierr = PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass");CHKERRQ(ierr);
629a13144ffSStefano Zampini           ierr = ISView(extcols[i],NULL);CHKERRQ(ierr);
630a13144ffSStefano Zampini         }
631a13144ffSStefano Zampini         eerr = PETSC_TRUE;
632a13144ffSStefano Zampini       }
633a13144ffSStefano Zampini     }
634a13144ffSStefano Zampini   }
635a13144ffSStefano Zampini   ierr = MatRestoreRowIJ( lG,0,PETSC_FALSE,PETSC_FALSE,&i, &ii, &jj,&done);CHKERRQ(ierr);
636a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done);CHKERRQ(ierr);
637a13144ffSStefano Zampini   ierr = PetscFree2(extrow,gidxs);CHKERRQ(ierr);
638a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
639a13144ffSStefano Zampini   /* an error should not occur at this point */
640a13144ffSStefano Zampini   if (eerr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS");
641a13144ffSStefano Zampini 
6424e64d54eSstefano_zampini   /* Check the number of endpoints */
6434e64d54eSstefano_zampini   /* TODO: add case for circular edge */
6444e64d54eSstefano_zampini   ierr = PetscBTCreate(nv,&btvc);CHKERRQ(ierr);
6454e64d54eSstefano_zampini   ierr = MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
6464e64d54eSstefano_zampini   for (i=0;i<nee;i++) {
6474e64d54eSstefano_zampini     PetscInt size, found = 0;
6484e64d54eSstefano_zampini 
6494e64d54eSstefano_zampini     ierr = PetscBTMemzero(nv,btvc);CHKERRQ(ierr);
6504e64d54eSstefano_zampini     ierr = ISGetLocalSize(eedges[i],&size);CHKERRQ(ierr);
6514e64d54eSstefano_zampini     ierr = ISGetIndices(eedges[i],&idxs);CHKERRQ(ierr);
6524e64d54eSstefano_zampini     for (j=0;j<size;j++) {
6534e64d54eSstefano_zampini       PetscInt k,ee = idxs[j];
6544e64d54eSstefano_zampini       for (k=ii[ee];k<ii[ee+1];k++) {
6554e64d54eSstefano_zampini         PetscInt vv = jj[k];
6564e64d54eSstefano_zampini         if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) {
6574e64d54eSstefano_zampini           found++;
6584e64d54eSstefano_zampini         }
6594e64d54eSstefano_zampini       }
6604e64d54eSstefano_zampini     }
6614e64d54eSstefano_zampini     ierr = ISRestoreIndices(eedges[i],&idxs);CHKERRQ(ierr);
6624e64d54eSstefano_zampini     if (found != 2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %d corners for edge %d\n",found,i);
6634e64d54eSstefano_zampini   }
6644e64d54eSstefano_zampini   ierr = MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
6654e64d54eSstefano_zampini   ierr = PetscBTDestroy(&btvc);CHKERRQ(ierr);
6664e64d54eSstefano_zampini   ierr = MatDestroy(&lGe);CHKERRQ(ierr);
6674e64d54eSstefano_zampini 
668a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
669a13144ffSStefano Zampini   /* Inspects columns of lG (rows of lGt) and make sure the change of basis will
670a13144ffSStefano Zampini      not interfere with neighbouring coarse edges */
671a13144ffSStefano Zampini   ierr = PetscMalloc1(nee+1,&emarks);CHKERRQ(ierr);
672a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
673a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
674a13144ffSStefano Zampini     PetscInt emax = 0,eemax = 0;
675a13144ffSStefano Zampini 
676a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
677a13144ffSStefano Zampini     ierr = PetscMemzero(emarks,(nee+1)*sizeof(PetscInt));CHKERRQ(ierr);
678a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++;
679a13144ffSStefano Zampini     for (j=1;j<nee+1;j++) {
680a13144ffSStefano Zampini       if (emax < emarks[j]) {
681a13144ffSStefano Zampini         emax = emarks[j];
682a13144ffSStefano Zampini         eemax = j;
683a13144ffSStefano Zampini       }
684a13144ffSStefano Zampini     }
685a13144ffSStefano Zampini     /* not relevant for edges */
686a13144ffSStefano Zampini     if (!eemax) continue;
687a13144ffSStefano Zampini 
688a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
689a13144ffSStefano Zampini       if (marks[jj[j]] && marks[jj[j]] != eemax) {
690a13144ffSStefano 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]);
691a13144ffSStefano Zampini       }
692a13144ffSStefano Zampini     }
693a13144ffSStefano Zampini   }
694a13144ffSStefano Zampini   ierr = PetscFree(emarks);CHKERRQ(ierr);
695a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
696a13144ffSStefano Zampini #endif
697a13144ffSStefano Zampini 
698a13144ffSStefano Zampini   /* Compute extended rows indices for edge blocks of the change of basis */
699a13144ffSStefano Zampini   ierr = MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
700a13144ffSStefano Zampini   ierr = MatSeqAIJGetMaxRowNonzeros(lGt,&extmem);CHKERRQ(ierr);
701a13144ffSStefano Zampini   extmem *= maxsize;
702a13144ffSStefano Zampini   ierr = PetscMalloc1(extmem*nee,&extrow);CHKERRQ(ierr);
703a13144ffSStefano Zampini   ierr = PetscMalloc1(nee,&extrows);CHKERRQ(ierr);
704a13144ffSStefano Zampini   ierr = PetscCalloc1(nee,&extrowcum);CHKERRQ(ierr);
705a13144ffSStefano Zampini   for (i=0;i<nv;i++) {
706a13144ffSStefano Zampini     PetscInt mark = 0,size,start;
707a13144ffSStefano Zampini     if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue;
708a13144ffSStefano Zampini     for (j=ii[i];j<ii[i+1];j++)
709a13144ffSStefano Zampini       if (marks[jj[j]] && !mark)
710a13144ffSStefano Zampini         mark = marks[jj[j]];
711a13144ffSStefano Zampini 
712a13144ffSStefano Zampini     /* not relevant */
713a13144ffSStefano Zampini     if (!mark) continue;
714a13144ffSStefano Zampini 
715a13144ffSStefano Zampini     /* import extended row */
716a13144ffSStefano Zampini     mark--;
717a13144ffSStefano Zampini     start = mark*extmem+extrowcum[mark];
718a13144ffSStefano Zampini     size = ii[i+1]-ii[i];
719a13144ffSStefano Zampini #if defined(PETSC_USE_DEBUG)
720a13144ffSStefano Zampini     if (extrowcum[mark] + size > extmem) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %d > %d",extrowcum[mark] + size,extmem);
721a13144ffSStefano Zampini #endif
722a13144ffSStefano Zampini     ierr = PetscMemcpy(extrow+start,jj+ii[i],size*sizeof(PetscInt));CHKERRQ(ierr);
723a13144ffSStefano Zampini     extrowcum[mark] += size;
724a13144ffSStefano Zampini   }
725a13144ffSStefano Zampini   ierr = MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done);CHKERRQ(ierr);
726a13144ffSStefano Zampini   cum  = 0;
727a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
728a13144ffSStefano Zampini     PetscInt size = extrowcum[i],*start = extrow + i*extmem;
729a13144ffSStefano Zampini     ierr = PetscSortRemoveDupsInt(&size,start);CHKERRQ(ierr);
730a13144ffSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i]);CHKERRQ(ierr);
731a13144ffSStefano Zampini     cum  = PetscMax(cum,size);
732a13144ffSStefano Zampini   }
733a13144ffSStefano Zampini   ierr = PetscFree(extrowcum);CHKERRQ(ierr);
734a13144ffSStefano Zampini   ierr = PetscFree(marks);CHKERRQ(ierr);
735a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btv);CHKERRQ(ierr);
736a13144ffSStefano Zampini   ierr = PetscBTDestroy(&btvcand);CHKERRQ(ierr);
737a13144ffSStefano Zampini 
738a13144ffSStefano Zampini   /* Workspace for lapack inner calls and VecSetValues */
739a13144ffSStefano Zampini   ierr = PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork);CHKERRQ(ierr);
740a13144ffSStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
741a13144ffSStefano Zampini   for (i=0;i<maxsize;i++) vals[i] = 1.;
742a13144ffSStefano Zampini 
743a13144ffSStefano Zampini   /* Create vectors for quadrature rules */
744a13144ffSStefano Zampini   ierr = PetscMalloc1(nquads,&quads);CHKERRQ(ierr);
745a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
746a13144ffSStefano Zampini     ierr = MatCreateVecs(pc->pmat,&quads[i],NULL);CHKERRQ(ierr);
747a13144ffSStefano Zampini     ierr = VecSetLocalToGlobalMapping(quads[i],el2g);CHKERRQ(ierr);
748a13144ffSStefano Zampini   }
749a13144ffSStefano Zampini   ierr = PCBDDCNullSpaceCreate(comm,PETSC_FALSE,nquads,quads,&nnsp);CHKERRQ(ierr);
750a13144ffSStefano Zampini 
751a13144ffSStefano Zampini   /* Create change of basis matrix (preallocation can be improved) */
752a13144ffSStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
753a13144ffSStefano Zampini   ierr = MatSetSizes(T,Le,Le,Ne,Ne);CHKERRQ(ierr);
754a13144ffSStefano Zampini   ierr = MatSetType(T,MATAIJ);CHKERRQ(ierr);
755a13144ffSStefano Zampini   ierr = MatSeqAIJSetPreallocation(T,10,NULL);CHKERRQ(ierr);
756a13144ffSStefano Zampini   ierr = MatMPIAIJSetPreallocation(T,10,NULL,10,NULL);CHKERRQ(ierr);
757a13144ffSStefano Zampini   ierr = MatSetLocalToGlobalMapping(T,el2g,el2g);CHKERRQ(ierr);
758a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
759a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
760a13144ffSStefano Zampini   ierr = MatSetOption(T,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
761a13144ffSStefano Zampini 
762a13144ffSStefano Zampini   /* Defaults to identity */
763a13144ffSStefano Zampini   ierr = VecSet(tvec,1.0);CHKERRQ(ierr);
764a13144ffSStefano Zampini   ierr = MatDiagonalSet(T,tvec,INSERT_VALUES);CHKERRQ(ierr);
765a13144ffSStefano Zampini   ierr = VecDestroy(&tvec);CHKERRQ(ierr);
766a13144ffSStefano Zampini 
767a13144ffSStefano Zampini   for (i=0;i<nee;i++) {
768a13144ffSStefano Zampini     Mat Gins = NULL, GKins = NULL;
769a13144ffSStefano Zampini 
770a13144ffSStefano Zampini     ierr = PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],&Gins,&GKins,work,rwork);CHKERRQ(ierr);
771a13144ffSStefano Zampini     if (Gins && GKins) {
772a13144ffSStefano Zampini       PetscScalar    *data;
773a13144ffSStefano Zampini       const PetscInt *rows,*cols;
774a13144ffSStefano Zampini       PetscInt       nrh,nch,nrc,ncc;
775a13144ffSStefano Zampini 
776a13144ffSStefano Zampini       ierr = ISGetIndices(eedges[i],&cols);CHKERRQ(ierr);
777a13144ffSStefano Zampini       /* H1 */
778a13144ffSStefano Zampini       ierr = ISGetIndices(extrows[i],&rows);CHKERRQ(ierr);
779a13144ffSStefano Zampini       ierr = MatGetSize(Gins,&nrh,&nch);CHKERRQ(ierr);
780a13144ffSStefano Zampini       ierr = MatDenseGetArray(Gins,&data);CHKERRQ(ierr);
781a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES);CHKERRQ(ierr);
782a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(Gins,&data);CHKERRQ(ierr);
783a13144ffSStefano Zampini       ierr = ISRestoreIndices(extrows[i],&rows);CHKERRQ(ierr);
784a13144ffSStefano Zampini       /* complement */
785a13144ffSStefano Zampini       ierr = MatGetSize(GKins,&nrc,&ncc);CHKERRQ(ierr);
786a13144ffSStefano Zampini       if (ncc > nquads-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet supported ncc %d nquads %d",ncc,nquads);
787a13144ffSStefano 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);
788a13144ffSStefano Zampini       ierr = MatDenseGetArray(GKins,&data);CHKERRQ(ierr);
789a13144ffSStefano Zampini       ierr = MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES);CHKERRQ(ierr);
790a13144ffSStefano Zampini       ierr = MatDenseRestoreArray(GKins,&data);CHKERRQ(ierr);
791a13144ffSStefano Zampini       /* Gins kernel quadratures */
792a13144ffSStefano Zampini       for (j=0;j<ncc;j++) {
793a13144ffSStefano Zampini         ierr = VecSetValueLocal(quads[j],cols[nch+j],1.,INSERT_VALUES);CHKERRQ(ierr);
794a13144ffSStefano Zampini       }
795a13144ffSStefano Zampini       /* H1 average */
796a13144ffSStefano Zampini       ierr = VecSetValuesLocal(quads[nquads-1],nch,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
797a13144ffSStefano Zampini       ierr = ISRestoreIndices(eedges[i],&cols);CHKERRQ(ierr);
798a13144ffSStefano Zampini     }
799a13144ffSStefano Zampini     ierr = ISDestroy(&extrows[i]);CHKERRQ(ierr);
800a13144ffSStefano Zampini     ierr = ISDestroy(&extcols[i]);CHKERRQ(ierr);
801a13144ffSStefano Zampini     ierr = MatDestroy(&Gins);CHKERRQ(ierr);
802a13144ffSStefano Zampini     ierr = MatDestroy(&GKins);CHKERRQ(ierr);
803a13144ffSStefano Zampini   }
804a13144ffSStefano Zampini 
805a13144ffSStefano Zampini   /* Start assembling */
806a13144ffSStefano Zampini   ierr = MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
807a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
808a13144ffSStefano Zampini     ierr = VecAssemblyBegin(quads[i]);CHKERRQ(ierr);
809a13144ffSStefano Zampini   }
810a13144ffSStefano Zampini 
811a13144ffSStefano Zampini   /* Free */
812a13144ffSStefano Zampini   ierr = PetscFree(extrow);CHKERRQ(ierr);
813a13144ffSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&vl2g);CHKERRQ(ierr);
814a13144ffSStefano Zampini   ierr = PetscFree2(work,rwork);CHKERRQ(ierr);
815a13144ffSStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
816a13144ffSStefano Zampini   ierr = PetscFree(extrows);CHKERRQ(ierr);
817a13144ffSStefano Zampini   ierr = PetscFree(extcols);CHKERRQ(ierr);
818a13144ffSStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&eedges,&primals);CHKERRQ(ierr);
819a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
820a13144ffSStefano Zampini   ierr = MatDestroy(&lGt);CHKERRQ(ierr);
821a13144ffSStefano Zampini   ierr = MatDestroy(&lG);CHKERRQ(ierr);
822a13144ffSStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
823a13144ffSStefano Zampini 
824a13144ffSStefano Zampini   /* Complete assembling */
825a13144ffSStefano Zampini   ierr = MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
826a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
827a13144ffSStefano Zampini     ierr = VecAssemblyEnd(quads[i]);CHKERRQ(ierr);
828a13144ffSStefano Zampini   }
829a13144ffSStefano Zampini   for (i=0;i<nquads;i++) {
830a13144ffSStefano Zampini     ierr = VecDestroy(&quads[i]);CHKERRQ(ierr);
831a13144ffSStefano Zampini   }
832a13144ffSStefano Zampini   ierr = PetscFree(quads);CHKERRQ(ierr);
833a13144ffSStefano Zampini 
834a13144ffSStefano Zampini   /* tell PCBDDC the topography has been analyzed */
835a13144ffSStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
836a13144ffSStefano Zampini 
837a13144ffSStefano Zampini   /* set change of basis */
838a13144ffSStefano Zampini   ierr = PCBDDCSetChangeOfBasisMat(pc,T,PETSC_FALSE);CHKERRQ(ierr);
839a13144ffSStefano Zampini   ierr = MatDestroy(&T);CHKERRQ(ierr);
840a13144ffSStefano Zampini 
841a13144ffSStefano Zampini   /* set quadratures */
842a13144ffSStefano Zampini   ierr = MatSetNearNullSpace(pc->pmat,nnsp);CHKERRQ(ierr);
843a13144ffSStefano Zampini   ierr = MatNullSpaceDestroy(&nnsp);CHKERRQ(ierr);
844a13144ffSStefano Zampini 
845a13144ffSStefano Zampini   PetscFunctionReturn(0);
846a13144ffSStefano Zampini }
847a13144ffSStefano Zampini 
848d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights,
849d8203eabSStefano Zampini    and these can be collinear -> so cheat with MatNullSpaceCreate
850d8203eabSStefano Zampini    and create a suitable set of basis vectors first */
851d8203eabSStefano Zampini #undef __FUNCT__
852d8203eabSStefano Zampini #define __FUNCT__ "PCBDDCNullSpaceCreate"
853d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp)
854d8203eabSStefano Zampini {
855d8203eabSStefano Zampini   PetscErrorCode ierr;
856d8203eabSStefano Zampini   PetscInt       i;
857d8203eabSStefano Zampini 
858d8203eabSStefano Zampini   PetscFunctionBegin;
859d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) {
860d8203eabSStefano Zampini     PetscInt first,last;
861d8203eabSStefano Zampini 
862d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
86386fa73c5SStefano Zampini     if (last-first < 2*nvecs && has_const) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
864d8203eabSStefano Zampini     if (i>=first && i < last) {
865d8203eabSStefano Zampini       PetscScalar *data;
866d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
867d8203eabSStefano Zampini       if (!has_const) {
868d8203eabSStefano Zampini         data[i-first] = 1.;
869d8203eabSStefano Zampini       } else {
87086fa73c5SStefano Zampini         data[2*i-first] = 1./PetscSqrtReal(2.);
87186fa73c5SStefano Zampini         data[2*i-first+1] = -1./PetscSqrtReal(2.);
872d8203eabSStefano Zampini       }
873d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
874d8203eabSStefano Zampini     }
875d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
876d8203eabSStefano Zampini   }
877d8203eabSStefano Zampini   ierr = MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp);CHKERRQ(ierr);
878d8203eabSStefano Zampini   for (i=0;i<nvecs;i++) { /* reset vectors */
879d8203eabSStefano Zampini     PetscInt first,last;
880d8203eabSStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
881d8203eabSStefano Zampini     if (i>=first && i < last) {
882d8203eabSStefano Zampini       PetscScalar *data;
883d8203eabSStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
884d8203eabSStefano Zampini       if (!has_const) {
885d8203eabSStefano Zampini         data[i-first] = 0.;
886d8203eabSStefano Zampini       } else {
88786fa73c5SStefano Zampini         data[2*i-first] = 0.;
88886fa73c5SStefano Zampini         data[2*i-first+1] = 0.;
889d8203eabSStefano Zampini       }
890d8203eabSStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
891d8203eabSStefano Zampini     }
892d8203eabSStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
893d8203eabSStefano Zampini   }
894d8203eabSStefano Zampini   PetscFunctionReturn(0);
895d8203eabSStefano Zampini }
896d8203eabSStefano Zampini 
897669cc0f4SStefano Zampini #undef __FUNCT__
898669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
8998ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
900669cc0f4SStefano Zampini {
901a198735bSStefano Zampini   Mat                    loc_divudotp;
902fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
9038ae0ca82SStefano Zampini   ISLocalToGlobalMapping map;
904669cc0f4SStefano Zampini   IS                     *faces,*edges;
905669cc0f4SStefano Zampini   PetscScalar            *vals;
906669cc0f4SStefano Zampini   const PetscScalar      *array;
907669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
9081ae86dd6SStefano Zampini   PetscMPIInt            rank;
909a198735bSStefano Zampini   PetscErrorCode         ierr;
910669cc0f4SStefano Zampini 
911669cc0f4SStefano Zampini   PetscFunctionBegin;
912669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
913669cc0f4SStefano Zampini   if (graph->twodim) {
914669cc0f4SStefano Zampini     lmaxneighs = 2;
915669cc0f4SStefano Zampini   } else {
916669cc0f4SStefano Zampini     lmaxneighs = 1;
917669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
918669cc0f4SStefano Zampini       const PetscInt *idxs;
919669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
920669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
921669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
922669cc0f4SStefano Zampini     }
923669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
924669cc0f4SStefano Zampini   }
925669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
926669cc0f4SStefano Zampini   maxsize = 0;
927669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
928669cc0f4SStefano Zampini     PetscInt nn;
929669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
930669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
931669cc0f4SStefano Zampini   }
932669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
933669cc0f4SStefano Zampini     PetscInt nn;
934669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
935669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
936669cc0f4SStefano Zampini   }
937669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
938669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
939669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
9408ae0ca82SStefano Zampini   if (!transpose) {
9418ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&map,NULL);CHKERRQ(ierr);
9428ae0ca82SStefano Zampini   } else {
9438ae0ca82SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,NULL,&map);CHKERRQ(ierr);
9448ae0ca82SStefano Zampini   }
945669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
9461ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
947d8203eabSStefano Zampini   ierr = PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
948669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
9498ae0ca82SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],map);CHKERRQ(ierr);
950669cc0f4SStefano Zampini   }
951d8203eabSStefano Zampini 
952669cc0f4SStefano Zampini   /* compute local quad vec */
953a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
9548ae0ca82SStefano Zampini   if (!transpose) {
955a198735bSStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
9568ae0ca82SStefano Zampini   } else {
9578ae0ca82SStefano Zampini     ierr = MatCreateVecs(loc_divudotp,&p,&v);CHKERRQ(ierr);
9588ae0ca82SStefano Zampini   }
959669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
9608ae0ca82SStefano Zampini   if (!transpose) {
961a198735bSStefano Zampini     ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
9628ae0ca82SStefano Zampini   } else {
9638ae0ca82SStefano Zampini     ierr = MatMult(loc_divudotp,p,v);CHKERRQ(ierr);
9648ae0ca82SStefano Zampini   }
965fa23a32eSStefano Zampini   if (vl2l) {
966fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
967fa23a32eSStefano Zampini   } else {
968fa23a32eSStefano Zampini     vins = v;
969fa23a32eSStefano Zampini   }
970fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
971669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
9729a962809SStefano Zampini 
9731ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
9741ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
975669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
976669cc0f4SStefano Zampini     const PetscInt    *idxs;
977669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
978669cc0f4SStefano Zampini 
979669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
980669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
981669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
9821ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
983669cc0f4SStefano Zampini     idx = -(idx+1);
984669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
985669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
986669cc0f4SStefano Zampini   }
987669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
988669cc0f4SStefano Zampini     const PetscInt    *idxs;
989669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
990669cc0f4SStefano Zampini 
991669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
992669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
993669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
9941ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
995669cc0f4SStefano Zampini     idx = -(idx+1);
996669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
997669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
998669cc0f4SStefano Zampini   }
999c8272957SStefano Zampini   ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
1000fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
1001fa23a32eSStefano Zampini   if (vl2l) {
1002fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
1003fa23a32eSStefano Zampini   }
1004669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1005669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
1006669cc0f4SStefano Zampini 
1007669cc0f4SStefano Zampini   /* assemble near null space */
1008669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1009669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
1010669cc0f4SStefano Zampini   }
1011669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
1012669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
1013669cc0f4SStefano Zampini   }
1014669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
1015669cc0f4SStefano Zampini   PetscFunctionReturn(0);
1016669cc0f4SStefano Zampini }
1017669cc0f4SStefano Zampini 
1018669cc0f4SStefano Zampini 
1019a3df083aSStefano Zampini #undef __FUNCT__
10201f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
10211f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
10221f4df5f7SStefano Zampini {
10231f4df5f7SStefano Zampini   PetscErrorCode ierr;
10241f4df5f7SStefano Zampini   Vec            local,global;
10251f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
10261f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
10271f4df5f7SStefano Zampini 
10281f4df5f7SStefano Zampini   PetscFunctionBegin;
10291f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
10301f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
10311f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
10321f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
10331f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
10341f4df5f7SStefano Zampini       PetscInt i;
10351f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
10361f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
10371f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
10381f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
10391f4df5f7SStefano Zampini       }
10401f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
10411f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
10421f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
10431f4df5f7SStefano Zampini     }
10441f4df5f7SStefano Zampini   } else {
1045986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
10461f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
1047986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
1048986cdee1SStefano Zampini       if (i > 1) {
1049986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
10501f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
10511f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
10521f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
10531f4df5f7SStefano Zampini         }
10541f4df5f7SStefano Zampini       }
10551f4df5f7SStefano Zampini     }
1056986cdee1SStefano Zampini   }
10571f4df5f7SStefano Zampini 
10581f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
10591f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
10601f4df5f7SStefano Zampini   }
10611f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
10621f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
10631f4df5f7SStefano Zampini   }
10641f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
10651f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
10661f4df5f7SStefano Zampini   }
10671f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
10681f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
10691f4df5f7SStefano Zampini   PetscFunctionReturn(0);
10701f4df5f7SStefano Zampini }
10711f4df5f7SStefano Zampini 
10721f4df5f7SStefano Zampini #undef __FUNCT__
10733e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
10743e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
10753e589ea0SStefano Zampini {
10763e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
10773e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
10783e589ea0SStefano Zampini   PetscErrorCode    ierr;
10793e589ea0SStefano Zampini 
10803e589ea0SStefano Zampini   PetscFunctionBegin;
10813e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
10823e589ea0SStefano Zampini     PetscFunctionReturn(0);
10833e589ea0SStefano Zampini   }
10843e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
10853e589ea0SStefano Zampini     Vec swap;
10863e589ea0SStefano Zampini 
10873e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
10883e589ea0SStefano Zampini     swap = pcbddc->work_change;
10893e589ea0SStefano Zampini     pcbddc->work_change = r;
10903e589ea0SStefano Zampini     r = swap;
10913e589ea0SStefano Zampini   }
10923e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10933e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10943e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
10953e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
10963e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10973e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10983e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
10993e589ea0SStefano Zampini     Vec swap;
11003e589ea0SStefano Zampini 
11013e589ea0SStefano Zampini     swap = r;
11023e589ea0SStefano Zampini     r = pcbddc->work_change;
11033e589ea0SStefano Zampini     pcbddc->work_change = swap;
11043e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
11053e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
11063e589ea0SStefano Zampini   }
11073e589ea0SStefano Zampini   PetscFunctionReturn(0);
11083e589ea0SStefano Zampini }
11093e589ea0SStefano Zampini 
11103e589ea0SStefano Zampini #undef __FUNCT__
1111a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
1112a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
1113a3df083aSStefano Zampini {
1114a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1115a3df083aSStefano Zampini   PetscErrorCode          ierr;
1116a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
1117a3df083aSStefano Zampini 
1118a3df083aSStefano Zampini   PetscFunctionBegin;
1119a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
1120a3df083aSStefano Zampini   if (transpose) {
1121a3df083aSStefano Zampini     apply_right = ctx->apply_left;
1122a3df083aSStefano Zampini     apply_left = ctx->apply_right;
1123a3df083aSStefano Zampini   } else {
1124a3df083aSStefano Zampini     apply_right = ctx->apply_right;
1125a3df083aSStefano Zampini     apply_left = ctx->apply_left;
1126a3df083aSStefano Zampini   }
1127a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
1128a3df083aSStefano Zampini   if (apply_right) {
1129a3df083aSStefano Zampini     const PetscScalar *ax;
1130a3df083aSStefano Zampini     PetscInt          nl,i;
1131a3df083aSStefano Zampini 
1132a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
1133a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
1134a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
1135a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);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       sum = 0.;
1143a3df083aSStefano Zampini       if (ctx->apply_p0) {
1144a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
1145a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1146a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1147a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
1148a3df083aSStefano Zampini         }
1149a3df083aSStefano Zampini       } else {
1150a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1151a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
1152a3df083aSStefano Zampini         }
1153a3df083aSStefano Zampini       }
1154a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
1155a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1156a3df083aSStefano Zampini     }
1157a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
1158a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
1159a3df083aSStefano Zampini   }
1160a3df083aSStefano Zampini   if (transpose) {
1161a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
1162a3df083aSStefano Zampini   } else {
1163a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
1164a3df083aSStefano Zampini   }
1165a3df083aSStefano Zampini   if (reset_x) {
1166a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
1167a3df083aSStefano Zampini   }
1168a3df083aSStefano Zampini   if (apply_left) {
1169a3df083aSStefano Zampini     PetscScalar *ay;
1170a3df083aSStefano Zampini     PetscInt    i;
1171a3df083aSStefano Zampini 
1172a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
1173a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
1174a3df083aSStefano Zampini       PetscScalar    sum,val;
1175a3df083aSStefano Zampini       const PetscInt *idxs;
1176a3df083aSStefano Zampini       PetscInt       nz,j;
1177a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1178a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1179a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
1180a3df083aSStefano Zampini       if (ctx->apply_p0) {
1181a3df083aSStefano Zampini         sum = 0.;
1182a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1183a3df083aSStefano Zampini           sum += ay[idxs[j]];
1184a3df083aSStefano Zampini           ay[idxs[j]] += val;
1185a3df083aSStefano Zampini         }
1186a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
1187a3df083aSStefano Zampini       } else {
1188a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
1189a3df083aSStefano Zampini           ay[idxs[j]] += val;
1190a3df083aSStefano Zampini         }
1191a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
1192a3df083aSStefano Zampini       }
1193a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
1194a3df083aSStefano Zampini     }
1195a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
1196a3df083aSStefano Zampini   }
1197a3df083aSStefano Zampini   PetscFunctionReturn(0);
1198a3df083aSStefano Zampini }
1199a3df083aSStefano Zampini 
1200a3df083aSStefano Zampini #undef __FUNCT__
1201a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
1202a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
1203a3df083aSStefano Zampini {
1204a3df083aSStefano Zampini   PetscErrorCode ierr;
1205a3df083aSStefano Zampini 
1206a3df083aSStefano Zampini   PetscFunctionBegin;
1207a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
1208a3df083aSStefano Zampini   PetscFunctionReturn(0);
1209a3df083aSStefano Zampini }
1210a3df083aSStefano Zampini 
1211a3df083aSStefano Zampini #undef __FUNCT__
1212a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
1213a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
1214a3df083aSStefano Zampini {
1215a3df083aSStefano Zampini   PetscErrorCode ierr;
1216a3df083aSStefano Zampini 
1217a3df083aSStefano Zampini   PetscFunctionBegin;
1218a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
1219a3df083aSStefano Zampini   PetscFunctionReturn(0);
1220a3df083aSStefano Zampini }
1221a3df083aSStefano Zampini 
1222a3df083aSStefano Zampini #undef __FUNCT__
1223a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
1224a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
1225a3df083aSStefano Zampini {
1226a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
1227a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
1228a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
1229a3df083aSStefano Zampini   PetscErrorCode          ierr;
1230a3df083aSStefano Zampini 
1231a3df083aSStefano Zampini   PetscFunctionBegin;
1232a3df083aSStefano Zampini   if (!restore) {
12331dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
1234a3df083aSStefano Zampini     PetscScalar        *work;
1235b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
1236a3df083aSStefano Zampini 
12379a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
12389a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
1239a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
1240a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
1241a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1242a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
1243a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
1244a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
1245a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
1246a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
1247a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
1248a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
1249a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
1250a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
1251059032f7SStefano Zampini     if (reuse) {
1252a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
12531dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
1254059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
1255059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
1256059032f7SStefano Zampini       PetscInt               i;
1257059032f7SStefano Zampini 
1258059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
1259059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1260059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1261059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1262059032f7SStefano Zampini       }
1263059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
12641dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
1265059032f7SStefano Zampini     }
1266a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
1267a3df083aSStefano Zampini     ctx->work = work;
1268a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
1269a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1270a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1271a3df083aSStefano Zampini     pcis->A_IB = A_IB;
1272a3df083aSStefano Zampini 
1273a3df083aSStefano Zampini     /* A_BI as A_IB^T */
1274a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
1275a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
1276a3df083aSStefano Zampini     pcis->A_BI = A_BI;
1277a3df083aSStefano Zampini   } else {
12781dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
12791dd7afcfSStefano Zampini       PetscFunctionReturn(0);
12801dd7afcfSStefano Zampini     }
1281a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
1282a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1283a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
12841dd7afcfSStefano Zampini     ctx->A = NULL;
12851dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
12861dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
12871dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
12881dd7afcfSStefano Zampini     if (ctx->free) {
1289059032f7SStefano Zampini       PetscInt i;
12901dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
1291059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1292059032f7SStefano Zampini       }
1293059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
1294059032f7SStefano Zampini     }
1295a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
1296a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
1297a3df083aSStefano Zampini   }
1298a3df083aSStefano Zampini   PetscFunctionReturn(0);
1299a3df083aSStefano Zampini }
1300a3df083aSStefano Zampini 
1301a3df083aSStefano Zampini /* used just in bddc debug mode */
1302a3df083aSStefano Zampini #undef __FUNCT__
1303a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
1304a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
1305a3df083aSStefano Zampini {
1306a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1307a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1308a3df083aSStefano Zampini   Mat            An;
1309a3df083aSStefano Zampini   PetscErrorCode ierr;
1310a3df083aSStefano Zampini 
1311a3df083aSStefano Zampini   PetscFunctionBegin;
1312a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
1313a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
1314a3df083aSStefano Zampini   if (is1) {
1315a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
1316a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
1317a3df083aSStefano Zampini   } else {
1318a3df083aSStefano Zampini     *B = An;
1319a3df083aSStefano Zampini   }
1320a3df083aSStefano Zampini   PetscFunctionReturn(0);
1321a3df083aSStefano Zampini }
1322a3df083aSStefano Zampini 
13231cf9b237SStefano Zampini /* TODO: add reuse flag */
13241cf9b237SStefano Zampini #undef __FUNCT__
13251cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
13261cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
13271cf9b237SStefano Zampini {
13281cf9b237SStefano Zampini   Mat            Bt;
13291cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
13301cf9b237SStefano Zampini   const PetscInt *ii,*ij;
13311cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
13321cf9b237SStefano Zampini   PetscBool      flg_row;
13331cf9b237SStefano Zampini   PetscErrorCode ierr;
13341cf9b237SStefano Zampini 
13351cf9b237SStefano Zampini   PetscFunctionBegin;
13361cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
13371cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
13381cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
13391cf9b237SStefano Zampini   nnz = n;
13401cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
13411cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
13421cf9b237SStefano Zampini   }
13431cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
13441cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
13451cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
13461cf9b237SStefano Zampini   nnz = 0;
13471cf9b237SStefano Zampini   bii[0] = 0;
13481cf9b237SStefano Zampini   for (i=0;i<n;i++) {
13491cf9b237SStefano Zampini     PetscInt j;
13501cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
13511cf9b237SStefano Zampini       PetscScalar entry = a[j];
13521cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
13531cf9b237SStefano Zampini         bij[nnz] = ij[j];
13541cf9b237SStefano Zampini         bdata[nnz] = entry;
13551cf9b237SStefano Zampini         nnz++;
13561cf9b237SStefano Zampini       }
13571cf9b237SStefano Zampini     }
13581cf9b237SStefano Zampini     bii[i+1] = nnz;
13591cf9b237SStefano Zampini   }
13601cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
13611cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
13621cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
13631cf9b237SStefano Zampini   {
13641cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
13651cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
13661cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
13671cf9b237SStefano Zampini   }
13681cf9b237SStefano Zampini   *B = Bt;
13691cf9b237SStefano Zampini   PetscFunctionReturn(0);
13701cf9b237SStefano Zampini }
13711cf9b237SStefano Zampini 
1372674ae819SStefano Zampini #undef __FUNCT__
13734f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
13744f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
13754f1b2e48SStefano Zampini {
13764f1b2e48SStefano Zampini   Mat                    B;
13774f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
13784f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
13794f1b2e48SStefano Zampini   PCBDDCGraph            graph;
13804f1b2e48SStefano Zampini   PetscInt               i,n;
13814f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
13824f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
13834f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
13844f1b2e48SStefano Zampini   PetscErrorCode         ierr;
13854f1b2e48SStefano Zampini 
13864f1b2e48SStefano Zampini   PetscFunctionBegin;
138763c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
138863c961adSStefano Zampini     *ncc = 0;
138963c961adSStefano Zampini     *cc = NULL;
139063c961adSStefano Zampini     PetscFunctionReturn(0);
139163c961adSStefano Zampini   }
13924f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
13934f1b2e48SStefano Zampini   if (!isseqaij && filter) {
13941cf9b237SStefano Zampini     PetscBool isseqdense;
13951cf9b237SStefano Zampini 
13961cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
13971cf9b237SStefano Zampini     if (!isseqdense) {
13984f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
13991cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
14001cf9b237SStefano Zampini       PetscScalar *array;
14011cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
14021cf9b237SStefano Zampini 
14031cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
14041cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
14051cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
14061cf9b237SStefano Zampini       for (i=0;i<n;i++) {
14071cf9b237SStefano Zampini         PetscInt j;
14081cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
14091cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
14101cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
14111cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
14121cf9b237SStefano Zampini         }
14131cf9b237SStefano Zampini       }
14141cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
14159d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
14161cf9b237SStefano Zampini     }
14174f1b2e48SStefano Zampini   } else {
14184f1b2e48SStefano Zampini     B = A;
14194f1b2e48SStefano Zampini   }
14204f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
14214f1b2e48SStefano Zampini 
14224f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
14234f1b2e48SStefano Zampini   if (filter) {
14244f1b2e48SStefano Zampini     PetscScalar *data;
14254f1b2e48SStefano Zampini     PetscInt    j,cum;
14264f1b2e48SStefano Zampini 
14274f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
14284f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
14294f1b2e48SStefano Zampini     cum = 0;
14304f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
14314f1b2e48SStefano Zampini       PetscInt t;
14324f1b2e48SStefano Zampini 
14334f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
14344f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
14354f1b2e48SStefano Zampini           continue;
14364f1b2e48SStefano Zampini         }
14374f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
14384f1b2e48SStefano Zampini       }
14394f1b2e48SStefano Zampini       t = xadj_filtered[i];
14404f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
14414f1b2e48SStefano Zampini       cum += t;
14424f1b2e48SStefano Zampini     }
14434f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
14444f1b2e48SStefano Zampini   } else {
14454f1b2e48SStefano Zampini     xadj_filtered = NULL;
14464f1b2e48SStefano Zampini     adjncy_filtered = NULL;
14474f1b2e48SStefano Zampini   }
14484f1b2e48SStefano Zampini 
14494f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
14504f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
14514f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
14524f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
14534f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1454be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT);CHKERRQ(ierr);
14554f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
14564f1b2e48SStefano Zampini   if (xadj_filtered) {
14574f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
14584f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
14594f1b2e48SStefano Zampini   } else {
14604f1b2e48SStefano Zampini     graph->xadj = xadj;
14614f1b2e48SStefano Zampini     graph->adjncy = adjncy;
14624f1b2e48SStefano Zampini   }
14634f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
14644f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
14654f1b2e48SStefano Zampini   /* partial clean up */
14664f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
14674f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
14681cf9b237SStefano Zampini   if (A != B) {
14694f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
14704f1b2e48SStefano Zampini   }
14714f1b2e48SStefano Zampini 
14724f1b2e48SStefano Zampini   /* get back data */
14731cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
14741cf9b237SStefano Zampini   if (cc) {
14754f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
14764f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
14774f1b2e48SStefano 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);
14784f1b2e48SStefano Zampini     }
14794f1b2e48SStefano Zampini     *cc = cc_n;
14801cf9b237SStefano Zampini   }
14814f1b2e48SStefano Zampini   /* clean up graph */
14824f1b2e48SStefano Zampini   graph->xadj = 0;
14834f1b2e48SStefano Zampini   graph->adjncy = 0;
14844f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
14854f1b2e48SStefano Zampini   PetscFunctionReturn(0);
14864f1b2e48SStefano Zampini }
14874f1b2e48SStefano Zampini 
14884f1b2e48SStefano Zampini #undef __FUNCT__
14895408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
14905408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
14915408967cSStefano Zampini {
14925408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14935408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
1494dee84bffSStefano Zampini   IS             dirIS = NULL;
14954f1b2e48SStefano Zampini   PetscInt       i;
14965408967cSStefano Zampini   PetscErrorCode ierr;
14975408967cSStefano Zampini 
14985408967cSStefano Zampini   PetscFunctionBegin;
1499dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
15005408967cSStefano Zampini   if (zerodiag) {
15015408967cSStefano Zampini     Mat            A;
15025408967cSStefano Zampini     Vec            vec3_N;
15035408967cSStefano Zampini     PetscScalar    *vals;
15045408967cSStefano Zampini     const PetscInt *idxs;
1505d12d3064SStefano Zampini     PetscInt       nz,*count;
15065408967cSStefano Zampini 
15075408967cSStefano Zampini     /* p0 */
15085408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
15095408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
15105408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
15115408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
15124f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
15135408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
15145408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
15155408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
15165408967cSStefano Zampini     /* v_I */
15175408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
15185408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
15195408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
15205408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
15215408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
15225408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
15235408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
15245408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
15255408967cSStefano Zampini     if (dirIS) {
15265408967cSStefano Zampini       PetscInt n;
15275408967cSStefano Zampini 
15285408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
15295408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
15305408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
15315408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
15325408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
15335408967cSStefano Zampini     }
15345408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
15355408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
15365408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
15375408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
1538669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
15395408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
15405408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
15419a962809SStefano 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]));
15425408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
15435408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
1544d12d3064SStefano Zampini 
1545d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
1546d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
1547d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1548d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
1549d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
1550d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
15519a962809SStefano 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]);
1552d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
1553d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
15545408967cSStefano Zampini   }
1555dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
15565408967cSStefano Zampini 
15575408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
15585408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
15594f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
15605408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
15614f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
15625408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
1563f2a566d8SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
1564f2a566d8SStefano Zampini     PetscInt val = PetscRealPart(pcbddc->benign_p0[i]);
1565f2a566d8SStefano 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);
1566f2a566d8SStefano Zampini   }
15675408967cSStefano Zampini   PetscFunctionReturn(0);
15685408967cSStefano Zampini }
15695408967cSStefano Zampini 
15705408967cSStefano Zampini #undef __FUNCT__
1571339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
1572339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
1573339f8db1SStefano Zampini {
1574339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
15754f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
1576b0f5fe93SStefano Zampini   PetscInt       nz,n;
15771f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
15784f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
1579339f8db1SStefano Zampini   PetscErrorCode ierr;
1580339f8db1SStefano Zampini 
1581339f8db1SStefano Zampini   PetscFunctionBegin;
15829f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
15839f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1584a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
1585a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
1586a3df083aSStefano Zampini   }
1587a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1588a3df083aSStefano Zampini   pcbddc->benign_n = 0;
15891ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
15904f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
15914f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
15924f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
15931ae86dd6SStefano Zampini      since the local Schur complements are already SPD
15944f1b2e48SStefano Zampini   */
15954f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
15964f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
159740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
15984f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
15994f1b2e48SStefano Zampini 
16004f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
16014f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
16024f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
16034f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
1604ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
160540fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
160640fa8d13SStefano Zampini     if (!sorted) {
160740fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
160840fa8d13SStefano Zampini     }
160940fa8d13SStefano Zampini   } else {
161040fa8d13SStefano Zampini     pressures = NULL;
161140fa8d13SStefano Zampini   }
161297d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
161397d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
161427b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
161597d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
1616339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
1617339f8db1SStefano Zampini   if (!sorted) {
1618339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
1619339f8db1SStefano Zampini   }
1620339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
16214f1b2e48SStefano Zampini   if (!nz) {
16224f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
16234f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
162440fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
162540fa8d13SStefano Zampini   }
16264f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
16274f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
16284f1b2e48SStefano Zampini   zerodiag_subs = NULL;
16294f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
16301f4df5f7SStefano Zampini   n_interior_dofs = 0;
16311f4df5f7SStefano Zampini   interior_dofs = NULL;
16321f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
16331f4df5f7SStefano Zampini     PetscInt n,i,j;
16341f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
16351f4df5f7SStefano Zampini     PetscInt *iwork;
16361f4df5f7SStefano Zampini 
16371f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
16381f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16391f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
16401f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
164190648384SStefano Zampini     for (i=1;i<n_neigh;i++)
16421f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
16431f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
16441f4df5f7SStefano Zampini     for (i=0;i<n;i++)
16451f4df5f7SStefano Zampini       if (!iwork[i])
16461f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
16471f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
16481f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16491f4df5f7SStefano Zampini   }
16504f1b2e48SStefano Zampini   if (has_null_pressures) {
16514f1b2e48SStefano Zampini     IS             *subs;
16521f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
16531f4df5f7SStefano Zampini     const PetscInt *idxs;
16541f4df5f7SStefano Zampini     PetscScalar    *array;
16551f4df5f7SStefano Zampini     Vec            *work;
16561f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
16574f1b2e48SStefano Zampini 
16584f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
16594f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
16601f4df5f7SStefano 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) */
16611f4df5f7SStefano Zampini     if (pcbddc->current_level) {
16621f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
16631f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
16641f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
16651f4df5f7SStefano Zampini       /* work[0] = 1_p */
16661f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
16671f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
16681f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
16691f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
16701f4df5f7SStefano Zampini       /* work[0] = 1_v */
16711f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
16721f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
16731f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
16741f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
16751f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
16761f4df5f7SStefano Zampini     }
16774f1b2e48SStefano Zampini     if (nsubs > 1) {
16784f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
16794f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
16804f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
16814f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
16824f1b2e48SStefano Zampini         PetscInt               nl;
16834f1b2e48SStefano Zampini 
16844f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
16854f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
16864f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
16874f1b2e48SStefano Zampini         if (nl) {
16884f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
16894f1b2e48SStefano Zampini 
16901f4df5f7SStefano Zampini           if (pcbddc->current_level) {
16911f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
16921f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
16931f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
16941f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
16951f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
16961f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
16971f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
16981f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
16991f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
17001f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
17011f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
17021f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
17031f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
17041f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
17051f4df5f7SStefano Zampini                 break;
17061f4df5f7SStefano Zampini               }
17071f4df5f7SStefano Zampini             }
17081f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
17091f4df5f7SStefano Zampini           }
17101f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
17111f4df5f7SStefano Zampini             IS       t_bc;
17121f4df5f7SStefano Zampini             PetscInt nzb;
17131f4df5f7SStefano Zampini 
17141f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
17151f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
17161f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
17171f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
17181f4df5f7SStefano Zampini           }
17191f4df5f7SStefano Zampini           if (valid && pressures) {
17204f1b2e48SStefano Zampini             IS t_pressure_subs;
17214f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
17224f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
17234f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
17244f1b2e48SStefano Zampini           }
17254f1b2e48SStefano Zampini           if (valid) {
17264f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
17274f1b2e48SStefano Zampini             pcbddc->benign_n++;
17284f1b2e48SStefano Zampini           } else {
17294f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
17304f1b2e48SStefano Zampini           }
17314f1b2e48SStefano Zampini         }
17324f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
17334f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
17344f1b2e48SStefano Zampini       }
17354f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
17364f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
17371f4df5f7SStefano Zampini 
17381f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
17391f4df5f7SStefano Zampini         PetscInt nzb;
17401f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
17411f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
17421f4df5f7SStefano Zampini       }
17431f4df5f7SStefano Zampini       if (valid && pressures) {
17444f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
17454f1b2e48SStefano Zampini       }
17461f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
17471f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
17481f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
17491f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
17501f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
17511f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
17521f4df5f7SStefano Zampini               valid = PETSC_FALSE;
17531f4df5f7SStefano Zampini               break;
17541f4df5f7SStefano Zampini           }
17551f4df5f7SStefano Zampini         }
17561f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
17571f4df5f7SStefano Zampini       }
17584f1b2e48SStefano Zampini       if (valid) {
17594f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
1760ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
17614f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
17624f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
17634f1b2e48SStefano Zampini       }
17644f1b2e48SStefano Zampini     }
17651f4df5f7SStefano Zampini     if (pcbddc->current_level) {
17661f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
17674f1b2e48SStefano Zampini     }
17681f4df5f7SStefano Zampini   }
17691f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
17704f1b2e48SStefano Zampini 
17714f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1772b9b0e38cSStefano Zampini     PetscInt n;
1773b9b0e38cSStefano Zampini 
17744f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
17754f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
1776b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
1777b9b0e38cSStefano Zampini     if (n) {
17784f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
17794f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
17804f1b2e48SStefano Zampini     }
1781b9b0e38cSStefano Zampini   }
17824f1b2e48SStefano Zampini 
17834f1b2e48SStefano Zampini   /* final check for null pressures */
17844f1b2e48SStefano Zampini   if (zerodiag && pressures) {
17854f1b2e48SStefano Zampini     PetscInt nz,np;
17864f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
17874f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
17884f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
17894f1b2e48SStefano Zampini   }
17904f1b2e48SStefano Zampini 
17914f1b2e48SStefano Zampini   if (recompute_zerodiag) {
17924f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
17934f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
17944f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
17954f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
17964f1b2e48SStefano Zampini     } else {
17974f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
17984f1b2e48SStefano Zampini 
17994f1b2e48SStefano Zampini       nzn = 0;
18004f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
18014f1b2e48SStefano Zampini         PetscInt ns;
18024f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
18034f1b2e48SStefano Zampini         nzn += ns;
18044f1b2e48SStefano Zampini       }
18054f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
18064f1b2e48SStefano Zampini       nzn = 0;
18074f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
18084f1b2e48SStefano Zampini         PetscInt ns,*idxs;
18094f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
18104f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
18114f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
18124f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
18134f1b2e48SStefano Zampini         nzn += ns;
18144f1b2e48SStefano Zampini       }
18154f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
18164f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
18174f1b2e48SStefano Zampini     }
18184f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
18194f1b2e48SStefano Zampini   }
18204f1b2e48SStefano Zampini 
1821669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
1822a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
1823a198735bSStefano Zampini     Mat                    A,loc_divudotp;
1824a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
1825a198735bSStefano Zampini     IS                     row,col,isused = NULL;
1826a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
1827a198735bSStefano Zampini 
18281f4df5f7SStefano Zampini     if (pressures) {
18291f4df5f7SStefano Zampini       isused = pressures;
18301f4df5f7SStefano Zampini     } else {
18311f4df5f7SStefano Zampini       isused = zerodiag;
18321f4df5f7SStefano Zampini     }
1833a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
1834669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
18351ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
18361ae86dd6SStefano 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");
1837a198735bSStefano Zampini     n_isused = 0;
1838a198735bSStefano Zampini     if (isused) {
1839a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
1840a198735bSStefano Zampini     }
1841a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1842a198735bSStefano Zampini     st = st-n_isused;
18431ae86dd6SStefano Zampini     if (n) {
1844a198735bSStefano Zampini       const PetscInt *gidxs;
1845a198735bSStefano Zampini 
1846a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
1847a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
1848a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
1849a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
1850a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
1851a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
18521ae86dd6SStefano Zampini     } else {
1853a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
1854a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
1855a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
1856a198735bSStefano Zampini     }
1857a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
1858a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
1859a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
1860a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
1861a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
1862a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
1863a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
1864a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
1865a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1866a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
1867a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1868a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1869a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
1870a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
18711ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18721ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18731ae86dd6SStefano Zampini   }
1874b3afcdbeSStefano Zampini 
1875b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
18764f1b2e48SStefano Zampini   if (has_null_pressures) {
18774f1b2e48SStefano Zampini     IS             zerodiagc;
18784f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
18794f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
18804f1b2e48SStefano Zampini 
18814f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1882339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
1883339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
1884339f8db1SStefano Zampini     /* local change of basis for pressures */
1885339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
188697d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
1887339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
1888339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1889339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
18904f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
18914f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
18924f1b2e48SStefano Zampini       PetscInt nzs,j;
18934f1b2e48SStefano Zampini 
18944f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
18954f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
18964f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
18974f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
18984f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
18994f1b2e48SStefano Zampini     }
1900339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
1901339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1902339f8db1SStefano Zampini     /* set identity on velocities */
1903339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
1904339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
1905339f8db1SStefano Zampini     }
19064f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
19074f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
19089f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
19094f1b2e48SStefano 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);
1910339f8db1SStefano Zampini     /* set change on pressures */
19114f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
19124f1b2e48SStefano Zampini       PetscScalar *array;
19134f1b2e48SStefano Zampini       PetscInt    nzs;
19144f1b2e48SStefano Zampini 
19154f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
19164f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
19174f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
1918339f8db1SStefano Zampini         PetscScalar vals[2];
1919339f8db1SStefano Zampini         PetscInt    cols[2];
1920339f8db1SStefano Zampini 
1921339f8db1SStefano Zampini         cols[0] = idxs[i];
19224f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
1923339f8db1SStefano Zampini         vals[0] = 1.;
1924b0f5fe93SStefano Zampini         vals[1] = 1.;
19254f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1926339f8db1SStefano Zampini       }
19274f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
19284f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
19294f1b2e48SStefano Zampini       array[nzs-1] = 1.;
19304f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
19314f1b2e48SStefano Zampini       /* store local idxs for p0 */
19324f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
19334f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
1934339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
19354f1b2e48SStefano Zampini     }
1936339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1937339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1938a3df083aSStefano Zampini     /* project if needed */
1939a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
19401dd7afcfSStefano Zampini       Mat M;
19411dd7afcfSStefano Zampini 
19421dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1943339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
19441dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
19451dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
1946a3df083aSStefano Zampini     }
19474f1b2e48SStefano Zampini     /* store global idxs for p0 */
19484f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1949339f8db1SStefano Zampini   }
1950ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
19514f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
1952b0f5fe93SStefano Zampini 
1953b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
1954b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
195527b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
195627b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1957339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
1958339f8db1SStefano Zampini   PetscFunctionReturn(0);
1959339f8db1SStefano Zampini }
1960339f8db1SStefano Zampini 
1961339f8db1SStefano Zampini #undef __FUNCT__
1962015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
1963015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
1964efc2fbd9SStefano Zampini {
1965efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1966de9d7bd0SStefano Zampini   PetscScalar    *array;
1967efc2fbd9SStefano Zampini   PetscErrorCode ierr;
1968efc2fbd9SStefano Zampini 
1969efc2fbd9SStefano Zampini   PetscFunctionBegin;
1970efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
1971efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
19724f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1973efc2fbd9SStefano Zampini   }
1974de9d7bd0SStefano Zampini   if (get) {
1975efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
19764f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
19774f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1978efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1979de9d7bd0SStefano Zampini   } else {
1980de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1981de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1982de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1983de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1984efc2fbd9SStefano Zampini   }
1985efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1986efc2fbd9SStefano Zampini }
1987efc2fbd9SStefano Zampini 
1988efc2fbd9SStefano Zampini #undef __FUNCT__
1989c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1990c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1991c263805aSStefano Zampini {
1992c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1993c263805aSStefano Zampini   PetscErrorCode ierr;
1994c263805aSStefano Zampini 
1995c263805aSStefano Zampini   PetscFunctionBegin;
1996c263805aSStefano Zampini   /* TODO: add error checking
1997c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1998c263805aSStefano Zampini     - cannot push before pop.
19991c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
2000c263805aSStefano Zampini   */
20014f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
2002efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
2003efc2fbd9SStefano Zampini   }
2004c263805aSStefano Zampini   if (pop) {
2005a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
20064f1b2e48SStefano Zampini       IS       is_p0;
20074f1b2e48SStefano Zampini       MatReuse reuse;
2008c263805aSStefano Zampini 
2009c263805aSStefano Zampini       /* extract B_0 */
20104f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
20114f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
20124f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
20134f1b2e48SStefano Zampini       }
20144f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
20154f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
2016c263805aSStefano Zampini       /* remove rows and cols from local problem */
2017c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
201897d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
20194f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
20204f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
2021a3df083aSStefano Zampini     } else {
2022a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
2023a3df083aSStefano Zampini       PetscScalar *vals;
2024a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
2025a3df083aSStefano Zampini 
2026a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
2027a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
2028a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
20290b5adadeSStefano Zampini         PetscInt *nnz;
2030a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
2031a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
2032a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2033331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
2034331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
2035331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
2036331e053bSStefano Zampini           nnz[i] = n - nnz[i];
2037331e053bSStefano Zampini         }
2038331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
2039331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
2040331e053bSStefano Zampini       }
2041a3df083aSStefano Zampini 
2042a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
2043a3df083aSStefano Zampini         PetscScalar *array;
2044a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
2045a3df083aSStefano Zampini 
2046a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
2047a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2048a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2049a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
2050a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2051a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
2052a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
2053a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
2054a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
2055a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
2056a3df083aSStefano Zampini         cum = 0;
2057a3df083aSStefano Zampini         for (j=0;j<n;j++) {
205822db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
2059a3df083aSStefano Zampini             vals[cum] = array[j];
2060a3df083aSStefano Zampini             idxs_ins[cum] = j;
2061a3df083aSStefano Zampini             cum++;
2062a3df083aSStefano Zampini           }
2063a3df083aSStefano Zampini         }
2064a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
2065a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
2066a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
2067a3df083aSStefano Zampini       }
2068a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2069a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2070a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
2071a3df083aSStefano Zampini     }
2072c263805aSStefano Zampini   } else { /* push */
2073a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
20744f1b2e48SStefano Zampini       PetscInt i;
20754f1b2e48SStefano Zampini 
20764f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
20774f1b2e48SStefano Zampini         PetscScalar *B0_vals;
20784f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
20794f1b2e48SStefano Zampini 
20804f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
20814f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
20827b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
20834f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
20844f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
20854f1b2e48SStefano Zampini       }
2086c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2087c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2088a3df083aSStefano Zampini     } else {
2089a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
2090a3df083aSStefano Zampini     }
2091c263805aSStefano Zampini   }
2092c263805aSStefano Zampini   PetscFunctionReturn(0);
2093c263805aSStefano Zampini }
2094c263805aSStefano Zampini 
2095c263805aSStefano Zampini #undef __FUNCT__
2096b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
209708122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
2098b1b3d7a2SStefano Zampini {
2099b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
210008122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
210108122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
210208122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
210308122e43SStefano Zampini   PetscScalar     *work,lwork;
210408122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
210508122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
210608122e43SStefano Zampini   PetscReal       *eigs,thresh;
21071b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
2108f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
210908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
211008122e43SStefano Zampini   PetscReal       *rwork;
211108122e43SStefano Zampini #endif
2112b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
2113b1b3d7a2SStefano Zampini 
2114b1b3d7a2SStefano Zampini   PetscFunctionBegin;
2115b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
2116af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
2117af25d912SStefano 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);
211806a4e24aSStefano Zampini 
2119fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2120fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2121fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2122fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
21231575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2124fd14bc51SStefano Zampini   }
2125fd14bc51SStefano Zampini 
2126e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
2127e496cd5dSStefano 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);
2128e496cd5dSStefano Zampini   }
2129e496cd5dSStefano Zampini 
213008122e43SStefano Zampini   /* max size of subsets */
213108122e43SStefano Zampini   mss = 0;
213208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
213308122e43SStefano Zampini     PetscInt subset_size;
2134862806e4SStefano Zampini 
213508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
213608122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
213708122e43SStefano Zampini   }
213808122e43SStefano Zampini 
213908122e43SStefano Zampini   /* min/max and threshold */
214008122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
2141f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
214208122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
2143f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
2144f6f667cfSStefano Zampini   if (nmin) {
2145f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
2146f6f667cfSStefano Zampini   }
214708122e43SStefano Zampini 
214808122e43SStefano Zampini   /* allocate lapack workspace */
214908122e43SStefano Zampini   cum = cum2 = 0;
215008122e43SStefano Zampini   maxneigs = 0;
215108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
215208122e43SStefano Zampini     PetscInt n,subset_size;
2153f6f667cfSStefano Zampini 
215408122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
215508122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
21569162d606SStefano Zampini     cum += subset_size;
21579162d606SStefano Zampini     cum2 += subset_size*n;
215808122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
215908122e43SStefano Zampini   }
216008122e43SStefano Zampini   if (mss) {
21619ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
216208122e43SStefano Zampini       PetscBLASInt B_itype = 1;
216308122e43SStefano Zampini       PetscBLASInt B_N = mss;
21644c6709b3SStefano Zampini       PetscReal    zero = 0.0;
21654c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
216608122e43SStefano Zampini 
216708122e43SStefano Zampini       B_lwork = -1;
216808122e43SStefano Zampini       S = NULL;
216908122e43SStefano Zampini       St = NULL;
2170a58a30b4SStefano Zampini       eigs = NULL;
2171a58a30b4SStefano Zampini       eigv = NULL;
2172a58a30b4SStefano Zampini       B_iwork = NULL;
2173a58a30b4SStefano Zampini       B_ifail = NULL;
2174d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2175d1710679SStefano Zampini       rwork = NULL;
2176d1710679SStefano Zampini #endif
21778bec7fa6SStefano Zampini       thresh = 1.0;
217808122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
217908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
218008122e43SStefano 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));
218108122e43SStefano Zampini #else
218208122e43SStefano 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));
218308122e43SStefano Zampini #endif
218408122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
218508122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
218608122e43SStefano Zampini     } else {
218708122e43SStefano Zampini         /* TODO */
218808122e43SStefano Zampini     }
218908122e43SStefano Zampini   } else {
219008122e43SStefano Zampini     lwork = 0;
219108122e43SStefano Zampini   }
219208122e43SStefano Zampini 
219308122e43SStefano Zampini   nv = 0;
2194d62866d3SStefano 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) */
2195d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
219608122e43SStefano Zampini   }
21974c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
2198f6f667cfSStefano Zampini   if (allocated_S_St) {
2199f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
2200f6f667cfSStefano Zampini   }
2201f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
220208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
220308122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
220408122e43SStefano Zampini #endif
22059162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
22069162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
22079162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
220808122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
22099162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
221008122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
221108122e43SStefano Zampini 
221208122e43SStefano Zampini   maxneigs = 0;
221372b8c272SStefano Zampini   cum = cumarray = 0;
22149162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
22159162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
2216d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
221708122e43SStefano Zampini     const PetscInt *idxs;
221808122e43SStefano Zampini 
2219d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
222008122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
222108122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
222208122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
222308122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
22249162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
22259162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
222608122e43SStefano Zampini     }
2227d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
222808122e43SStefano Zampini   }
222908122e43SStefano Zampini 
223008122e43SStefano Zampini   if (mss) { /* multilevel */
223108122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
223208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
223308122e43SStefano Zampini   }
223408122e43SStefano Zampini 
2235ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
223608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
223708122e43SStefano Zampini     const PetscInt *idxs;
22389d54b7f4SStefano Zampini     PetscReal      upper,lower;
2239862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
224008122e43SStefano Zampini     PetscBLASInt   B_N;
2241aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
224208122e43SStefano Zampini 
22439d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
22449d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
22459d54b7f4SStefano Zampini       lower = thresh;
22469d54b7f4SStefano Zampini     } else {
22479d54b7f4SStefano Zampini       upper = 1./thresh;
22489d54b7f4SStefano Zampini       lower = 0.;
22499d54b7f4SStefano Zampini     }
2250862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
2251ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
2252f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
2253f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
22549ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
2255aff50787SStefano Zampini         PetscInt j,k;
2256aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
2257aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
2258aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
225908122e43SStefano Zampini         }
226008122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
2261aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
2262aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
2263aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
2264aff50787SStefano Zampini           }
226508122e43SStefano Zampini         }
226608122e43SStefano Zampini       } else {
226708122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
226808122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
226908122e43SStefano Zampini       }
22708bec7fa6SStefano Zampini     } else {
2271f6f667cfSStefano Zampini       S = Sarray + cumarray;
2272f6f667cfSStefano Zampini       St = Starray + cumarray;
22738bec7fa6SStefano Zampini     }
2274aff50787SStefano Zampini     /* see if we can save some work */
2275b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
2276aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
2277aff50787SStefano Zampini     }
2278aff50787SStefano Zampini 
2279b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
2280aff50787SStefano Zampini       B_neigs = 0;
2281aff50787SStefano Zampini     } else {
22829ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
228308122e43SStefano Zampini         PetscBLASInt B_itype = 1;
2284f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
22854c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
22869552c7c7SStefano Zampini         PetscInt     nmin_s;
2287b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
228808122e43SStefano Zampini 
2289fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
22908bec7fa6SStefano 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]]);
2291fd14bc51SStefano Zampini         }
2292d16cbb6bSStefano Zampini 
2293b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
2294b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
2295b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
2296b7ab4a40SStefano Zampini         }
2297b7ab4a40SStefano Zampini 
229808122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2299b7ab4a40SStefano Zampini         if (compute_range) {
2300d16cbb6bSStefano Zampini 
2301d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
230208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
23039d54b7f4SStefano 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));
230408122e43SStefano Zampini #else
23059d54b7f4SStefano 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));
230608122e43SStefano Zampini #endif
2307b7ab4a40SStefano Zampini         } else if (!same_data) {
2308d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
2309d16cbb6bSStefano Zampini           B_IL = 1;
2310d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
23119d54b7f4SStefano 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));
2312d16cbb6bSStefano Zampini #else
23139d54b7f4SStefano 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));
2314d16cbb6bSStefano Zampini #endif
2315b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
2316b7ab4a40SStefano Zampini           PetscInt k;
2317b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
2318b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
2319b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
2320b7ab4a40SStefano Zampini           nmin = nmax;
2321b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2322b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
2323b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
2324b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
2325b7ab4a40SStefano Zampini           }
2326d16cbb6bSStefano Zampini         }
232708122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
232808122e43SStefano Zampini         if (B_ierr) {
23296c4ed002SBarry 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);
23306c4ed002SBarry 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);
23316c4ed002SBarry 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);
233208122e43SStefano Zampini         }
233308122e43SStefano Zampini 
233408122e43SStefano Zampini         if (B_neigs > nmax) {
2335fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2336fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
2337fd14bc51SStefano Zampini           }
23389d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
233908122e43SStefano Zampini           B_neigs = nmax;
234008122e43SStefano Zampini         }
234108122e43SStefano Zampini 
23429552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
23439552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
234408122e43SStefano Zampini           PetscBLASInt B_neigs2;
234508122e43SStefano Zampini 
23469d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
2347f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
23489d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
23499d54b7f4SStefano Zampini           } else {
23509d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
23519d54b7f4SStefano Zampini             B_IU = nmin_s;
23529d54b7f4SStefano Zampini           }
2353fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
2354fd14bc51SStefano 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);
2355fd14bc51SStefano Zampini           }
23569ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
23571ae86dd6SStefano Zampini             PetscInt j,k;
235808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
23591ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
23601ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
23611ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
236208122e43SStefano Zampini               }
236308122e43SStefano Zampini             }
236408122e43SStefano Zampini           } else {
236508122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
236608122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
236708122e43SStefano Zampini           }
236808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
236908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
23709d54b7f4SStefano 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));
237108122e43SStefano Zampini #else
23729d54b7f4SStefano 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));
237308122e43SStefano Zampini #endif
237408122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
237508122e43SStefano Zampini           B_neigs += B_neigs2;
237608122e43SStefano Zampini         }
237708122e43SStefano Zampini         if (B_ierr) {
23786c4ed002SBarry 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);
23796c4ed002SBarry 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);
23806c4ed002SBarry 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);
238108122e43SStefano Zampini         }
2382fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
2383ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
238408122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
238508122e43SStefano Zampini             if (eigs[j] == 0.0) {
2386ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
238708122e43SStefano Zampini             } else {
23889d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
2389ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
23909d54b7f4SStefano Zampini               } else {
23919d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
23929d54b7f4SStefano Zampini               }
2393fd14bc51SStefano Zampini             }
239408122e43SStefano Zampini           }
239508122e43SStefano Zampini         }
239608122e43SStefano Zampini       } else {
239708122e43SStefano Zampini           /* TODO */
239808122e43SStefano Zampini       }
2399aff50787SStefano Zampini     }
24006c3e6151SStefano Zampini     /* change the basis back to the original one */
24016c3e6151SStefano Zampini     if (sub_schurs->change) {
240272b8c272SStefano Zampini       Mat change,phi,phit;
24036c3e6151SStefano Zampini 
24046c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
24056c3e6151SStefano Zampini         PetscInt ii;
24066c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
24076c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
24086c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
2409684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2410684229deSStefano Zampini             PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]);
2411684229deSStefano Zampini             PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]);
2412684229deSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2413684229deSStefano Zampini #else
24146c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
2415684229deSStefano Zampini #endif
24166c3e6151SStefano Zampini           }
24176c3e6151SStefano Zampini         }
24186c3e6151SStefano Zampini       }
241972b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
24206c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
242172b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
24226c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
24236c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
24246c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
24256c3e6151SStefano Zampini     }
24268bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
24278bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
24289162d606SStefano Zampini     if (B_neigs) {
24299162d606SStefano 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);
2430fd14bc51SStefano Zampini 
2431fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
24329552c7c7SStefano Zampini         PetscInt ii;
24339552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
2434ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
24359552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
2436ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
2437ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2438ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
2439ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
2440ac47001eSStefano Zampini #else
2441ac47001eSStefano 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);
2442ac47001eSStefano Zampini #endif
24439552c7c7SStefano Zampini           }
24449552c7c7SStefano Zampini         }
2445fd14bc51SStefano Zampini       }
24469162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
24479162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
24489162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
24499162d606SStefano Zampini       cum++;
245008122e43SStefano Zampini     }
245108122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
245208122e43SStefano Zampini     /* shift for next computation */
245308122e43SStefano Zampini     cumarray += subset_size*subset_size;
245408122e43SStefano Zampini   }
2455fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
2456fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2457fd14bc51SStefano Zampini   }
245808122e43SStefano Zampini 
245908122e43SStefano Zampini   if (mss) {
246008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
246108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
2462f6f667cfSStefano Zampini     /* destroy matrices (junk) */
2463f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
2464f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
246508122e43SStefano Zampini   }
2466f6f667cfSStefano Zampini   if (allocated_S_St) {
2467f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
2468f6f667cfSStefano Zampini   }
2469f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
247008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
247108122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
247208122e43SStefano Zampini #endif
247308122e43SStefano Zampini   if (pcbddc->dbg_flag) {
24741b968477SStefano Zampini     PetscInt maxneigs_r;
2475b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
24769b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
247708122e43SStefano Zampini   }
247808122e43SStefano Zampini   PetscFunctionReturn(0);
247908122e43SStefano Zampini }
2480b1b3d7a2SStefano Zampini 
2481674ae819SStefano Zampini #undef __FUNCT__
2482c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
2483c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
2484c8587f34SStefano Zampini {
24858629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
2486c8587f34SStefano Zampini   PetscErrorCode ierr;
2487c8587f34SStefano Zampini 
2488c8587f34SStefano Zampini   PetscFunctionBegin;
2489f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
24905e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
2491c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
2492c8587f34SStefano Zampini 
2493684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
24940fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
2495684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2496c8587f34SStefano Zampini 
24978629588bSStefano Zampini   /*
24988629588bSStefano Zampini      Setup local correction and local part of coarse basis.
24998629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
25008629588bSStefano Zampini   */
250147f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
25028629588bSStefano Zampini 
25038629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
25048629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
25058629588bSStefano Zampini 
25068629588bSStefano Zampini   /* free */
25078629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
2508c8587f34SStefano Zampini   PetscFunctionReturn(0);
2509c8587f34SStefano Zampini }
2510c8587f34SStefano Zampini 
2511c8587f34SStefano Zampini #undef __FUNCT__
2512674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
2513674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
2514674ae819SStefano Zampini {
2515674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2516674ae819SStefano Zampini   PetscErrorCode ierr;
2517674ae819SStefano Zampini 
2518674ae819SStefano Zampini   PetscFunctionBegin;
2519674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
252030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
2521674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
2522785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2523674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
2524f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2525f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2526785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
252763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
252863602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
2529674ae819SStefano Zampini   PetscFunctionReturn(0);
2530674ae819SStefano Zampini }
2531674ae819SStefano Zampini 
2532674ae819SStefano Zampini #undef __FUNCT__
2533674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
2534674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
2535674ae819SStefano Zampini {
2536674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
25374f1b2e48SStefano Zampini   PetscInt       i;
2538674ae819SStefano Zampini   PetscErrorCode ierr;
2539674ae819SStefano Zampini 
2540674ae819SStefano Zampini   PetscFunctionBegin;
2541a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
2542b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2543674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
254416909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
25451dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
2546674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2547669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
2548fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
2549a13144ffSStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2550674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
255171582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_FALSE;
25524f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
25534f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
25544f1b2e48SStefano Zampini   }
25554f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
2556b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
2557b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
2558b334f244SStefano Zampini   }
2559674ae819SStefano Zampini   PetscFunctionReturn(0);
2560674ae819SStefano Zampini }
2561674ae819SStefano Zampini 
2562674ae819SStefano Zampini #undef __FUNCT__
2563674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
2564674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
2565674ae819SStefano Zampini {
2566674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2567674ae819SStefano Zampini   PetscErrorCode ierr;
2568674ae819SStefano Zampini 
2569674ae819SStefano Zampini   PetscFunctionBegin;
2570674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
257158da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
2572ca92afb2SStefano Zampini     PetscScalar *array;
257306656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
257406656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
257558da7f69SStefano Zampini   }
2576674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2577674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
257815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
257915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2580674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
2581674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
2582674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
258306656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
2584674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2585674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
25868ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2587674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2588674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2589674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2590f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
2591f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
2592f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2593f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2594727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
25950e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2596f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
259770cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
259881d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
25990369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
26001dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
26014f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
26028b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2603ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
2604ca92afb2SStefano Zampini     PetscInt i;
2605ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
2606ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
2607ca92afb2SStefano Zampini     }
2608ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
2609ca92afb2SStefano Zampini   }
26104f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
2611674ae819SStefano Zampini   PetscFunctionReturn(0);
2612674ae819SStefano Zampini }
2613674ae819SStefano Zampini 
2614674ae819SStefano Zampini #undef __FUNCT__
2615f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
2616f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
26176bfb1811SStefano Zampini {
26186bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
26196bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
26206bfb1811SStefano Zampini   VecType        impVecType;
26214f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
26226bfb1811SStefano Zampini   PetscErrorCode ierr;
26236bfb1811SStefano Zampini 
26246bfb1811SStefano Zampini   PetscFunctionBegin;
26256c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
2626e7b262bdSStefano Zampini   /* get sizes */
26274f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
2628b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
26296bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
2630e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
2631e7b262bdSStefano Zampini   /* R nodes */
2632e7b262bdSStefano Zampini   old_size = -1;
2633e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
2634e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
2635e7b262bdSStefano Zampini   }
2636e7b262bdSStefano Zampini   if (n_R != old_size) {
2637e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
2638e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
26396bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
26406bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
26416bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
26426bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
2643e7b262bdSStefano Zampini   }
2644e7b262bdSStefano Zampini   /* local primal dofs */
2645e7b262bdSStefano Zampini   old_size = -1;
2646e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
2647e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
2648e7b262bdSStefano Zampini   }
2649e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
2650e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
265183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
2652e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
26536bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
2654e7b262bdSStefano Zampini   }
2655e7b262bdSStefano Zampini   /* local explicit constraints */
2656e7b262bdSStefano Zampini   old_size = -1;
2657e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
2658e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
2659e7b262bdSStefano Zampini   }
2660e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
2661e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
266283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
266383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
266483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
266583b7ccabSStefano Zampini   }
26666bfb1811SStefano Zampini   PetscFunctionReturn(0);
26676bfb1811SStefano Zampini }
26686bfb1811SStefano Zampini 
26696bfb1811SStefano Zampini #undef __FUNCT__
267047f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
267147f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
267288ebb749SStefano Zampini {
267325084f0cSStefano Zampini   PetscErrorCode  ierr;
267425084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
267588ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
267688ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2677d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
267825084f0cSStefano Zampini   /* submatrices of local problem */
267980677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
268006656605SStefano Zampini   /* submatrices of local coarse problem */
268106656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
268225084f0cSStefano Zampini   /* working matrices */
268306656605SStefano Zampini   Mat             C_CR;
268425084f0cSStefano Zampini   /* additional working stuff */
268506656605SStefano Zampini   PC              pc_R;
26864f1b2e48SStefano Zampini   Mat             F;
26875cbda25cSStefano Zampini   Vec             dummy_vec;
2688a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
268925084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
269006656605SStefano Zampini   PetscScalar     *work;
269106656605SStefano Zampini   PetscInt        *idx_V_B;
2692ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
269306656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
2694ffd830a3SStefano Zampini 
269525084f0cSStefano Zampini   /* some shortcuts to scalars */
269606656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
269788ebb749SStefano Zampini 
269888ebb749SStefano Zampini   PetscFunctionBegin;
26999a962809SStefano 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");
2700ffd830a3SStefano Zampini 
2701ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
2702b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
27034f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
2704b371cd4fSStefano Zampini   n_B = pcis->n_B;
2705b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
270688ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
270788ebb749SStefano Zampini 
270888ebb749SStefano Zampini   /* vertices in boundary numbering */
2709785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
27100e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
27116c4ed002SBarry 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);
271288ebb749SStefano Zampini 
271306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
2714019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
271506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
271606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
271706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
271806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
271906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
272006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
272106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
272206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
272306656605SStefano Zampini 
272406656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
272506656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
272606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
272706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
272806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
2729ffd830a3SStefano Zampini   lda_rhs = n_R;
2730a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
273106656605SStefano Zampini   if (isLU || isILU || isCHOL) {
273206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
2733b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
2734df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2735d62866d3SStefano Zampini     MatFactorType      type;
2736d62866d3SStefano Zampini 
2737df4d28bfSStefano Zampini     F = reuse_solver->F;
27386816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
2739d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
2740ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
274122db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
274206656605SStefano Zampini   } else {
274306656605SStefano Zampini     F = NULL;
274406656605SStefano Zampini   }
274506656605SStefano Zampini 
2746ffd830a3SStefano Zampini   /* allocate workspace */
2747ffd830a3SStefano Zampini   n = 0;
2748ffd830a3SStefano Zampini   if (n_constraints) {
2749ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
2750ffd830a3SStefano Zampini   }
2751ffd830a3SStefano Zampini   if (n_vertices) {
2752ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
2753ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
2754ffd830a3SStefano Zampini   }
2755ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
2756ffd830a3SStefano Zampini 
27575cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
27585cbda25cSStefano Zampini   dummy_vec = NULL;
27595cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
27605cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
27615cbda25cSStefano Zampini   }
27625cbda25cSStefano Zampini 
276388ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
276488ebb749SStefano Zampini   if (n_constraints) {
276572b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
276606656605SStefano Zampini     IS          is_aux;
276780677318SStefano Zampini     PetscScalar *array,*array2;
276806656605SStefano Zampini 
2769f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
277080677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
277188ebb749SStefano Zampini 
277225084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
277325084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
27748ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
277572b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
277688ebb749SStefano Zampini 
277780677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
277880677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
2779ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
278088ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
278106656605SStefano Zampini       const PetscScalar *row_cmat_values;
278206656605SStefano Zampini       const PetscInt    *row_cmat_indices;
278306656605SStefano Zampini       PetscInt          size_of_constraint,j;
278488ebb749SStefano Zampini 
278506656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
278606656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
2787ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
278806656605SStefano Zampini       }
278906656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
279006656605SStefano Zampini     }
2791ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
279206656605SStefano Zampini     if (F) {
279306656605SStefano Zampini       Mat B;
279406656605SStefano Zampini 
2795ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
2796a3df083aSStefano Zampini       if (need_benign_correction) {
2797df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2798a3df083aSStefano Zampini 
279972b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
280072b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2801a3df083aSStefano Zampini       }
280280677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
2803a3df083aSStefano Zampini       if (need_benign_correction) {
2804a3df083aSStefano Zampini         PetscScalar        *marr;
2805df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2806a3df083aSStefano Zampini 
2807a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
28085cbda25cSStefano Zampini         if (lda_rhs != n_R) {
28095cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
28105cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
28115cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
28125cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
28135cbda25cSStefano Zampini           }
28145cbda25cSStefano Zampini         } else {
2815a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
2816a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
28175cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2818a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2819a3df083aSStefano Zampini           }
28205cbda25cSStefano Zampini         }
2821a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
2822a3df083aSStefano Zampini       }
282306656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
282406656605SStefano Zampini     } else {
282580677318SStefano Zampini       PetscScalar *marr;
282680677318SStefano Zampini 
282780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
282806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
2829ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2830ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
283106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
283206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
283306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
283406656605SStefano Zampini       }
283580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
283606656605SStefano Zampini     }
283780677318SStefano Zampini     if (!pcbddc->switch_static) {
283880677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
283980677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
284080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
284180677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
2842ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
284380677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
284480677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
284580677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
284680677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
284780677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
284880677318SStefano Zampini       }
284980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
285080677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
285172b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
285280677318SStefano Zampini     } else {
2853ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2854ffd830a3SStefano Zampini         IS dummy;
2855ffd830a3SStefano Zampini 
2856ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
285772b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
2858ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
2859ffd830a3SStefano Zampini       } else {
286080677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
286180677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
2862ffd830a3SStefano Zampini       }
286325084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
286480677318SStefano Zampini     }
286580677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
286680677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
286780677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
286806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
286906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
287080677318SStefano Zampini     if (isCHOL) {
287180677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
287280677318SStefano Zampini     } else {
287325084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
287480677318SStefano Zampini     }
287580677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
287606656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
287725084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
287825084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
287925084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
288080677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
288172b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
288272b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
288306656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
288406656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
2885f4ddd8eeSStefano Zampini   }
2886fc227af8SStefano Zampini 
2887fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
288888ebb749SStefano Zampini   if (n_vertices) {
288906656605SStefano Zampini     IS is_aux;
28903a50541eSStefano Zampini 
2891b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
28926816873aSStefano Zampini       IS tis;
28936816873aSStefano Zampini 
28946816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
28956816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
28966816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
28976816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
28986816873aSStefano Zampini     } else {
28993a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
29006816873aSStefano Zampini     }
29019577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
29029577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
290304708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
290425084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
290588ebb749SStefano Zampini   }
290688ebb749SStefano Zampini 
290788ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
2908f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
290906656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
291006656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
291106656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
291206656605SStefano Zampini     }
2913f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
291406656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
291506656605SStefano Zampini       PetscScalar *marray;
291606656605SStefano Zampini 
291706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
291806656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
2919f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2920f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
2921f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
2922f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2923f4ddd8eeSStefano Zampini     }
2924f4ddd8eeSStefano Zampini   }
292506656605SStefano Zampini 
2926f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
292706656605SStefano Zampini     PetscScalar *marray;
292888ebb749SStefano Zampini 
292906656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
29308eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
293106656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
293288ebb749SStefano Zampini     }
29333301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
293406656605SStefano Zampini       n *= 2;
293588ebb749SStefano Zampini     }
293606656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
293706656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
293806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
29398eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
294006656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
294106656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
294288ebb749SStefano Zampini     }
29433301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
294406656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
29458eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
294606656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
294706656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
294888ebb749SStefano Zampini       }
294988ebb749SStefano Zampini     } else {
2950c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
2951c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
29521b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
2953c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
2954c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
2955c0553b1fSStefano Zampini       }
295688ebb749SStefano Zampini     }
295706656605SStefano Zampini   }
2958019a44ceSStefano Zampini 
295906656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
29604f1b2e48SStefano Zampini   p0_lidx_I = NULL;
29614f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
2962d12edf2fSStefano Zampini     const PetscInt *idxs;
2963d12edf2fSStefano Zampini 
2964d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
29654f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
29664f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
29674f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
29684f1b2e48SStefano Zampini     }
2969d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
2970d12edf2fSStefano Zampini   }
2971d16cbb6bSStefano Zampini 
297206656605SStefano Zampini   /* vertices */
297306656605SStefano Zampini   if (n_vertices) {
297416f15bc4SStefano Zampini 
2975af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
297604708bb6SStefano Zampini 
297716f15bc4SStefano Zampini     if (n_R) {
297814393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
297906656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
298016f15bc4SStefano Zampini       PetscScalar  *x,*y;
298104708bb6SStefano Zampini       PetscBool    isseqaij;
298206656605SStefano Zampini 
298321eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
298414393ed6SStefano Zampini       if (need_benign_correction) {
298514393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
298614393ed6SStefano Zampini         IS                     is_p0;
298714393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
298814393ed6SStefano Zampini 
298914393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
299014393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
299114393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2992af25d912SStefano 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);
299314393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
299414393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
299514393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
299614393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
299714393ed6SStefano Zampini       }
299814393ed6SStefano Zampini 
2999ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
3000af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3001ffd830a3SStefano Zampini       } else {
3002ca92afb2SStefano Zampini         PetscScalar    *av,*array;
3003ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
3004ca92afb2SStefano Zampini         PetscInt       n;
3005ca92afb2SStefano Zampini         PetscBool      flg_row;
3006ffd830a3SStefano Zampini 
3007ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
3008ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
30099d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
3010ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3011ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
3012ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
3013ca92afb2SStefano Zampini           PetscInt j;
3014ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
3015ffd830a3SStefano Zampini         }
3016ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3017ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3018ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
3019ffd830a3SStefano Zampini       }
3020ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3021a3df083aSStefano Zampini       if (need_benign_correction) {
3022df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3023a3df083aSStefano Zampini         PetscScalar        *marr;
3024a3df083aSStefano Zampini 
3025a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
302614393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
302714393ed6SStefano Zampini 
302814393ed6SStefano Zampini                | 0 0  0 | (V)
302914393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
303014393ed6SStefano Zampini                | 0 0 -1 | (p0)
303114393ed6SStefano Zampini 
303214393ed6SStefano Zampini         */
3033df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
303414393ed6SStefano Zampini           const PetscScalar *vals;
303514393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
303614393ed6SStefano Zampini           PetscInt          n,j,nz;
303714393ed6SStefano Zampini 
3038df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3039df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
304014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
304114393ed6SStefano Zampini           for (j=0;j<n;j++) {
304214393ed6SStefano Zampini             PetscScalar val = vals[j];
304314393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
304414393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
304514393ed6SStefano Zampini           }
304614393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3047df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
304814393ed6SStefano Zampini         }
304972b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
305072b8c272SStefano Zampini       }
305172b8c272SStefano Zampini       if (F) {
305214393ed6SStefano Zampini         /* need to correct the rhs */
305372b8c272SStefano Zampini         if (need_benign_correction) {
305472b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
305572b8c272SStefano Zampini           PetscScalar        *marr;
305672b8c272SStefano Zampini 
305772b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
30585cbda25cSStefano Zampini           if (lda_rhs != n_R) {
30595cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
30605cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30615cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
30625cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30635cbda25cSStefano Zampini             }
30645cbda25cSStefano Zampini           } else {
3065a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3066a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30675cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
3068a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3069a3df083aSStefano Zampini             }
30705cbda25cSStefano Zampini           }
3071a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
3072a3df083aSStefano Zampini         }
307306656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
307414393ed6SStefano Zampini         /* need to correct the solution */
3075a3df083aSStefano Zampini         if (need_benign_correction) {
3076df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3077a3df083aSStefano Zampini           PetscScalar        *marr;
3078a3df083aSStefano Zampini 
3079a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
30805cbda25cSStefano Zampini           if (lda_rhs != n_R) {
30815cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
30825cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
30835cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
30845cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
30855cbda25cSStefano Zampini             }
30865cbda25cSStefano Zampini           } else {
3087a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
3088a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
30895cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
3090a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3091a3df083aSStefano Zampini             }
30925cbda25cSStefano Zampini           }
3093a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
3094a3df083aSStefano Zampini         }
309506656605SStefano Zampini       } else {
309606656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
309706656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
3098ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
3099ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
310006656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
310106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
310206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
310306656605SStefano Zampini         }
310406656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
310506656605SStefano Zampini       }
310680677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
3107ffd830a3SStefano Zampini       /* S_VV and S_CV */
310806656605SStefano Zampini       if (n_constraints) {
310906656605SStefano Zampini         Mat B;
311080677318SStefano Zampini 
3111ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
311280677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
3113ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
3114ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
311580677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
311680677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
311780677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
311880677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
311980677318SStefano Zampini         }
3120ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
312180677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
312280677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
3123ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
312480677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
312506656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
3126ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
3127ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
312806656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
312906656605SStefano Zampini       }
313004708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
313104708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
3132511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
313304708bb6SStefano Zampini       }
3134ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
3135ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
3136ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
3137ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
3138ffd830a3SStefano Zampini       }
313906656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
314014393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
314114393ed6SStefano Zampini       if (need_benign_correction) {
3142df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
314314393ed6SStefano Zampini         PetscScalar      *marr,*sums;
314414393ed6SStefano Zampini 
314514393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
314614393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
3147df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
314814393ed6SStefano Zampini           const PetscScalar *vals;
314914393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
315014393ed6SStefano Zampini           PetscInt          n,j,nz;
315114393ed6SStefano Zampini 
3152df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
3153df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
315414393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
315514393ed6SStefano Zampini             PetscInt k;
315614393ed6SStefano Zampini             sums[j] = 0.;
315714393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
315814393ed6SStefano Zampini           }
315914393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
316014393ed6SStefano Zampini           for (j=0;j<n;j++) {
316114393ed6SStefano Zampini             PetscScalar val = vals[j];
316214393ed6SStefano Zampini             PetscInt k;
316314393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
316414393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
316514393ed6SStefano Zampini             }
316614393ed6SStefano Zampini           }
316714393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
3168df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
316914393ed6SStefano Zampini         }
317014393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
317114393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
317214393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
317314393ed6SStefano Zampini       }
317480677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
317506656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
317606656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
317706656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
317806656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
317906656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
318006656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
318106656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3182d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
3183019a44ceSStefano Zampini     } else {
3184d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3185d16cbb6bSStefano Zampini     }
318621eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
3187d16cbb6bSStefano Zampini 
318806656605SStefano Zampini     /* coarse basis functions */
318906656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
319016f15bc4SStefano Zampini       PetscScalar *y;
319116f15bc4SStefano Zampini 
3192ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
319306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
319406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
319506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
319606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
319706656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
319806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
319906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
320006656605SStefano Zampini 
320106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
32024f1b2e48SStefano Zampini         PetscInt j;
32034f1b2e48SStefano Zampini 
320406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
320506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
320606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
320706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
320806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
32094f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
321006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
321106656605SStefano Zampini       }
321206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
321306656605SStefano Zampini     }
321404708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
321504708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
321606656605SStefano Zampini   }
32175cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
321806656605SStefano Zampini 
321906656605SStefano Zampini   if (n_constraints) {
322006656605SStefano Zampini     Mat B;
322106656605SStefano Zampini 
3222ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
322306656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
322480677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
322506656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
322606656605SStefano Zampini     if (n_vertices) {
322780677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
322880677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
322980677318SStefano Zampini       } else {
323080677318SStefano Zampini         Mat S_VCt;
323180677318SStefano Zampini 
3232ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
3233ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
323472b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
3235ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
3236ffd830a3SStefano Zampini         }
323780677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
323880677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
323980677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
324080677318SStefano Zampini       }
324106656605SStefano Zampini     }
324206656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
324306656605SStefano Zampini     /* coarse basis functions */
324406656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
324506656605SStefano Zampini       PetscScalar *y;
324606656605SStefano Zampini 
3247ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
324806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
324906656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
325006656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325106656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
325206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
325306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
325406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
32554f1b2e48SStefano Zampini         PetscInt j;
32564f1b2e48SStefano Zampini 
325706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
325806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
325906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
326006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
326106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
32624f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
326306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
326406656605SStefano Zampini       }
326506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
326606656605SStefano Zampini     }
326706656605SStefano Zampini   }
326880677318SStefano Zampini   if (n_constraints) {
326980677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
327080677318SStefano Zampini   }
32714f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
327272b8c272SStefano Zampini 
327372b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
327472b8c272SStefano Zampini   if (pcbddc->benign_n) {
327572b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
327672b8c272SStefano Zampini     IS          is_dummy;
327772b8c272SStefano Zampini     PetscScalar *data;
327872b8c272SStefano Zampini     PetscInt    j;
327972b8c272SStefano Zampini 
328072b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
328172b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
328272b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
328372b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
328486c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
328572b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
328672b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
328772b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
328872b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
328972b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
329072b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
329172b8c272SStefano Zampini       }
329272b8c272SStefano Zampini     }
329372b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
329472b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
329572b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
329672b8c272SStefano Zampini   }
3297019a44ceSStefano Zampini 
329806656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
32993301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
3300ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
3301ffd830a3SStefano Zampini     PetscScalar *marray;
330206656605SStefano Zampini 
330306656605SStefano Zampini     if (n_constraints) {
3304ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
330506656605SStefano Zampini 
3306af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
330706656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
3308ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
330916f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
331006656605SStefano Zampini       if (n_vertices) {
3311ffd830a3SStefano Zampini         Mat S_VCT;
331206656605SStefano Zampini 
331306656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
3314ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
331516f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
331606656605SStefano Zampini       }
3317ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
33185b782168SStefano Zampini     } else {
33195b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
332006656605SStefano Zampini     }
332116f15bc4SStefano Zampini     if (n_vertices && n_R) {
3322ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
3323ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
3324ffd830a3SStefano Zampini       PetscInt       n;
3325ffd830a3SStefano Zampini       PetscBool      flg_row;
332606656605SStefano Zampini 
3327ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
3328af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
3329ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3330ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
3331ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3332ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
3333ffd830a3SStefano Zampini         PetscInt j;
3334ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
3335ffd830a3SStefano Zampini       }
3336ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
3337ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
3338ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
333906656605SStefano Zampini     }
334006656605SStefano Zampini 
3341ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
3342ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
3343ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
3344ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
3345ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
334606656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
334706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
334806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
334906656605SStefano Zampini     }
3350ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
33515b782168SStefano Zampini     if (B_C) {
3352ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
3353ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
3354ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
3355ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
3356ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3357ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
3358ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
335906656605SStefano Zampini       }
3360ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
33615b782168SStefano Zampini     }
336206656605SStefano Zampini     /* coarse basis functions */
336306656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
336406656605SStefano Zampini       PetscScalar *y;
336506656605SStefano Zampini 
3366ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
336706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
336806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
336906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
337006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
337106656605SStefano Zampini       if (i<n_vertices) {
337206656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
337306656605SStefano Zampini       }
337406656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
337506656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
337606656605SStefano Zampini 
337706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
337806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
337906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
338006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
338306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
338406656605SStefano Zampini       }
338506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
338606656605SStefano Zampini     }
3387ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
3388ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
338906656605SStefano Zampini   }
3390d62866d3SStefano Zampini   /* free memory */
339188ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
339206656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
339306656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
339406656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
339506656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
3396d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
3397d62866d3SStefano Zampini   if (n_vertices) {
3398d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
3399d62866d3SStefano Zampini   }
3400d62866d3SStefano Zampini   if (n_constraints) {
3401d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
3402d62866d3SStefano Zampini   }
340388ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
340488ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
340588ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
3406d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
340788ebb749SStefano Zampini     Mat         coarse_sub_mat;
340825084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
340988ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
341088ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
341188ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
34128bec7fa6SStefano Zampini     Mat         C_B,CPHI;
34138bec7fa6SStefano Zampini     IS          is_dummy;
34148bec7fa6SStefano Zampini     Vec         mones;
341588ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
341688ebb749SStefano Zampini     PetscReal   real_value;
341788ebb749SStefano Zampini 
3418a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3419a3df083aSStefano Zampini       Mat A;
3420a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
3421a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3422a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3423a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3424a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3425a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
3426a3df083aSStefano Zampini     } else {
342788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
342888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
342988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
343088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3431a3df083aSStefano Zampini     }
343288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
343388ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3434ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
343588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
343688ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
343788ebb749SStefano Zampini     }
343888ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
343988ebb749SStefano Zampini 
344025084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
34413301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
344225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3443ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
344488ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
344588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
344688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
344788ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
344888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
344988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
345088ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
345188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
345288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
345388ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
345488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
345588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
345688ebb749SStefano Zampini     } else {
345788ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
345888ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
345988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
346088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
346188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
346288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
346388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
346488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
346588ebb749SStefano Zampini     }
346688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
346788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
346888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
3469511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
34704f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3471fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
3472d12edf2fSStefano Zampini       PetscScalar *data,*data2;
34734f1b2e48SStefano Zampini       PetscInt    j;
3474d12edf2fSStefano Zampini 
34754f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3476fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
3477d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
347886c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
3479d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
3480d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
34814f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
34824f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
3483d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
34844f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
34854f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
34864f1b2e48SStefano Zampini         }
3487d12edf2fSStefano Zampini       }
3488d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
3489d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
3490d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
3491d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3492d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
3493d12edf2fSStefano Zampini     }
3494d12edf2fSStefano Zampini #if 0
3495d12edf2fSStefano Zampini   {
3496d12edf2fSStefano Zampini     PetscViewer viewer;
3497d12edf2fSStefano Zampini     char filename[256];
3498ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
3499d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3500d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3501ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
3502ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
3503ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
3504d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
350572b8c272SStefano Zampini     if (save_change) {
350672b8c272SStefano Zampini       Mat phi_B;
350772b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
350872b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
350972b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
351072b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
351172b8c272SStefano Zampini     } else {
3512ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
3513ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
351472b8c272SStefano Zampini     }
3515ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
3516ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
3517ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
3518ffd830a3SStefano Zampini     }
3519ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
3520ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
3521ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
3522ffd830a3SStefano Zampini     }
352372b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
3524ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
3525ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
3526ffd830a3SStefano Zampini     }
3527d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3528d12edf2fSStefano Zampini   }
3529d12edf2fSStefano Zampini #endif
353081d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
35318bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
35321575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
353306656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
35348bec7fa6SStefano Zampini 
35358bec7fa6SStefano Zampini     /* check constraints */
3536a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
3537a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
35384f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
35398bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3540a00504b5SStefano Zampini     } else {
3541a00504b5SStefano Zampini       PetscScalar *data;
3542a00504b5SStefano Zampini       Mat         tmat;
3543a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3544a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
3545a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
3546a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3547a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3548a00504b5SStefano Zampini     }
35498bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
35508bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
35518bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
35528bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3553bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
3554ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
3555bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
3556bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
3557bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
3558bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
3559bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
356088ebb749SStefano Zampini     }
35618bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
35628bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
35638bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
35648bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
356525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
356688ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
356788ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
356888ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
356988ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
357088ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
357188ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
357288ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
357388ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
357488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
357588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
3576ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
357788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
357888ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
357988ebb749SStefano Zampini     }
358088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
358188ebb749SStefano Zampini   }
35828629588bSStefano Zampini   /* get back data */
35838629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
358488ebb749SStefano Zampini   PetscFunctionReturn(0);
358588ebb749SStefano Zampini }
358688ebb749SStefano Zampini 
358788ebb749SStefano Zampini #undef __FUNCT__
3588d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
3589d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
3590aa0d41d4SStefano Zampini {
3591d65f70fdSStefano Zampini   Mat            *work_mat;
3592d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
3593d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
3594c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
3595aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3596aa0d41d4SStefano Zampini 
3597aa0d41d4SStefano Zampini   PetscFunctionBegin;
3598d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
3599d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
3600d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
3601d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3602aa0d41d4SStefano Zampini 
3603d65f70fdSStefano Zampini   if (!rsorted) {
3604906d46d4SStefano Zampini     const PetscInt *idxs;
3605906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
3606aa0d41d4SStefano Zampini 
3607d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
3608d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
3609d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3610d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
3611aa0d41d4SStefano Zampini     }
3612d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
3613d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
3614d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
3615d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
3616aa0d41d4SStefano Zampini     }
3617d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
3618d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
3619d65f70fdSStefano Zampini   } else {
3620d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
3621d65f70fdSStefano Zampini     isrow_s = isrow;
3622aa0d41d4SStefano Zampini   }
3623906d46d4SStefano Zampini 
3624d65f70fdSStefano Zampini   if (!csorted) {
3625d65f70fdSStefano Zampini     if (isrow == iscol) {
3626d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
3627d65f70fdSStefano Zampini       iscol_s = isrow_s;
3628d65f70fdSStefano Zampini     } else {
3629d65f70fdSStefano Zampini       const PetscInt *idxs;
3630d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
3631906d46d4SStefano Zampini 
3632d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
3633d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
3634d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3635d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
3636d65f70fdSStefano Zampini       }
3637d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
3638d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
3639d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
3640d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
3641d65f70fdSStefano Zampini       }
3642d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
3643d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
3644d65f70fdSStefano Zampini     }
3645d65f70fdSStefano Zampini   } else {
3646d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
3647d65f70fdSStefano Zampini     iscol_s = iscol;
3648d65f70fdSStefano Zampini   }
3649d65f70fdSStefano Zampini 
3650d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3651d65f70fdSStefano Zampini 
3652d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
3653906d46d4SStefano Zampini     Mat      new_mat;
3654d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
3655906d46d4SStefano Zampini 
3656d65f70fdSStefano Zampini     if (!rsorted) {
3657d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
3658d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
3659d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
3660d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
3661906d46d4SStefano Zampini       }
3662d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
3663d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
3664d65f70fdSStefano Zampini     } else {
3665d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
3666906d46d4SStefano Zampini     }
3667d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
3668d65f70fdSStefano Zampini 
3669d65f70fdSStefano Zampini     if (!csorted) {
3670d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
3671d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
3672d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
3673d65f70fdSStefano Zampini       } else {
3674d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
3675d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
3676d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
3677d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
3678d65f70fdSStefano Zampini         }
3679d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
3680d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
3681d65f70fdSStefano Zampini       }
3682d65f70fdSStefano Zampini     } else {
3683d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
3684d65f70fdSStefano Zampini     }
3685d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
3686d65f70fdSStefano Zampini 
3687d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
3688d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
3689d65f70fdSStefano Zampini     work_mat[0] = new_mat;
3690d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
3691d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
3692d65f70fdSStefano Zampini   }
3693d65f70fdSStefano Zampini 
3694d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
3695d65f70fdSStefano Zampini   *B = work_mat[0];
3696d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
3697d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
3698d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
3699d65f70fdSStefano Zampini   PetscFunctionReturn(0);
3700d65f70fdSStefano Zampini }
3701d65f70fdSStefano Zampini 
3702d65f70fdSStefano Zampini #undef __FUNCT__
37035e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
37045e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
3705aa0d41d4SStefano Zampini {
3706aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
37075e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3708d65f70fdSStefano Zampini   Mat            new_mat;
37095e8657edSStefano Zampini   IS             is_local,is_global;
3710d65f70fdSStefano Zampini   PetscInt       local_size;
3711d65f70fdSStefano Zampini   PetscBool      isseqaij;
3712aa0d41d4SStefano Zampini   PetscErrorCode ierr;
3713aa0d41d4SStefano Zampini 
3714aa0d41d4SStefano Zampini   PetscFunctionBegin;
3715aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
37165e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
37175e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
3718b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
3719aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
3720d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
3721aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
3722906d46d4SStefano Zampini 
3723906d46d4SStefano Zampini   /* check */
3724906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
3725906d46d4SStefano Zampini     Vec       x,x_change;
3726906d46d4SStefano Zampini     PetscReal error;
3727906d46d4SStefano Zampini 
37285e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
3729906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
37305e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
3731e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3732e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3733d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
3734e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3735e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3736906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3737906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3738906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3739906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
3740906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
3741906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3742906d46d4SStefano Zampini   }
3743906d46d4SStefano Zampini 
374422d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
37459b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
374622d5777bSStefano Zampini   if (isseqaij) {
3747a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3748a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
3749aa0d41d4SStefano Zampini   } else {
3750a00504b5SStefano Zampini     Mat work_mat;
37511cf9b237SStefano Zampini 
3752a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
3753aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
3754a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
37551d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
3756aa0d41d4SStefano Zampini   }
37573301b35fSStefano Zampini   if (matis->A->symmetric_set) {
37583301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
3759e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
37603301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
3761e496cd5dSStefano Zampini #endif
37623301b35fSStefano Zampini   }
3763d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
3764aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
3765aa0d41d4SStefano Zampini }
3766aa0d41d4SStefano Zampini 
3767aa0d41d4SStefano Zampini #undef __FUNCT__
3768a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
37698ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
3770a64d13efSStefano Zampini {
3771a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
3772a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
3773d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
377453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
37753a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
37763a50541eSStefano Zampini   PetscInt        vbs,bs;
37776816873aSStefano Zampini   PetscBT         bitmask=NULL;
3778a64d13efSStefano Zampini   PetscErrorCode  ierr;
3779a64d13efSStefano Zampini 
3780a64d13efSStefano Zampini   PetscFunctionBegin;
3781b23d619eSStefano Zampini   /*
3782b23d619eSStefano Zampini     No need to setup local scatters if
3783b23d619eSStefano Zampini       - primal space is unchanged
3784b23d619eSStefano Zampini         AND
3785b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
3786b23d619eSStefano Zampini         AND
3787b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
3788b23d619eSStefano Zampini   */
3789b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
3790f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
3791f4ddd8eeSStefano Zampini   }
3792f4ddd8eeSStefano Zampini   /* destroy old objects */
3793f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
3794f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
3795f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
3796a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
3797b371cd4fSStefano Zampini   n_B = pcis->n_B;
3798b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
3799b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
38003a50541eSStefano Zampini 
3801a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
38026816873aSStefano Zampini 
380353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
3804b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
3805854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
3806a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
3807a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
38080e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
3809a64d13efSStefano Zampini     }
3810a64d13efSStefano Zampini 
3811a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
38124641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
38136816873aSStefano Zampini         idx_R_local[n_R++] = i;
3814a64d13efSStefano Zampini       }
3815a64d13efSStefano Zampini     }
3816df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
3817df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
38186816873aSStefano Zampini 
3819df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3820df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
38216816873aSStefano Zampini   }
38223a50541eSStefano Zampini 
38233a50541eSStefano Zampini   /* Block code */
38243a50541eSStefano Zampini   vbs = 1;
38253a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
38263a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
38273a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
38283a50541eSStefano Zampini     PetscInt  *vary;
3829b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
3830785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
38313a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
3832d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
3833d3df7717SStefano 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 */
38340e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
3835d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
38363a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
38373a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
38383a50541eSStefano Zampini           break;
38393a50541eSStefano Zampini         }
38403a50541eSStefano Zampini       }
3841d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
3842d3df7717SStefano Zampini     } else {
3843d3df7717SStefano Zampini       /* Verify directly the R set */
3844d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
3845d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
3846d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
3847d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
3848d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
3849d3df7717SStefano Zampini             break;
3850d3df7717SStefano Zampini           }
3851d3df7717SStefano Zampini         }
3852d3df7717SStefano Zampini       }
3853d3df7717SStefano Zampini     }
38543a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
38553a50541eSStefano Zampini       vbs = bs;
38563a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
38573a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
38583a50541eSStefano Zampini       }
38593a50541eSStefano Zampini     }
38603a50541eSStefano Zampini   }
38613a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
3862b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
3863df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
386453892102SStefano Zampini 
3865df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3866df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
386753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
3868df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
386953892102SStefano Zampini   } else {
38703a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
387153892102SStefano Zampini   }
3872a64d13efSStefano Zampini 
3873a64d13efSStefano Zampini   /* print some info if requested */
3874a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
3875a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3876a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38771575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3878a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
3879a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
38804f1b2e48SStefano 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);
3881a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3882a64d13efSStefano Zampini   }
3883a64d13efSStefano Zampini 
3884a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
3885b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
38866816873aSStefano Zampini     IS       is_aux1,is_aux2;
38876816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
38886816873aSStefano Zampini 
38893a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3890854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
3891854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
3892a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
38934641a718SStefano Zampini     for (i=0; i<n_D; i++) {
38944641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
38954641a718SStefano Zampini     }
3896a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3897a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
38984641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
38994641a718SStefano Zampini         aux_array1[j++] = i;
3900a64d13efSStefano Zampini       }
3901a64d13efSStefano Zampini     }
3902a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3903a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3904a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
39054641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
39064641a718SStefano Zampini         aux_array2[j++] = i;
3907a64d13efSStefano Zampini       }
3908a64d13efSStefano Zampini     }
3909a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3910a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
3911a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
3912a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3913a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
3914a64d13efSStefano Zampini 
39158eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3916785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
3917a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
39184641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
39194641a718SStefano Zampini           aux_array1[j++] = i;
3920a64d13efSStefano Zampini         }
3921a64d13efSStefano Zampini       }
3922a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3923a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
3924a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3925a64d13efSStefano Zampini     }
39264641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
39273a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3928d62866d3SStefano Zampini   } else {
3929df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
39306816873aSStefano Zampini     IS                 tis;
39316816873aSStefano Zampini     PetscInt           schur_size;
39326816873aSStefano Zampini 
3933df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
39346816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
3935df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
39366816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
39376816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
39386816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
39396816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
39406816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
3941d62866d3SStefano Zampini     }
3942d62866d3SStefano Zampini   }
3943a64d13efSStefano Zampini   PetscFunctionReturn(0);
3944a64d13efSStefano Zampini }
3945a64d13efSStefano Zampini 
3946304d26faSStefano Zampini 
3947304d26faSStefano Zampini #undef __FUNCT__
3948304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
3949684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
3950304d26faSStefano Zampini {
3951304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3952304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
3953304d26faSStefano Zampini   PC             pc_temp;
3954304d26faSStefano Zampini   Mat            A_RR;
3955f4ddd8eeSStefano Zampini   MatReuse       reuse;
3956304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
3957304d26faSStefano Zampini   PetscReal      value;
395804708bb6SStefano Zampini   PetscInt       n_D,n_R;
3959c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
3960304d26faSStefano Zampini   PetscErrorCode ierr;
3961e604994aSStefano Zampini   /* prefixes stuff */
3962312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
3963e604994aSStefano Zampini   size_t         len;
3964304d26faSStefano Zampini 
3965304d26faSStefano Zampini   PetscFunctionBegin;
3966304d26faSStefano Zampini 
3967e604994aSStefano Zampini   /* compute prefixes */
3968e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
3969e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
3970e604994aSStefano Zampini   if (!pcbddc->current_level) {
3971e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3972e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3973e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3974e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3975e604994aSStefano Zampini   } else {
3976e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3977312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3978e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3979e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3980312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3981312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
398234d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
398334d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3984e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3985e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3986e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3987e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3988e604994aSStefano Zampini   }
3989e604994aSStefano Zampini 
3990304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3991684f6988SStefano Zampini   if (dirichlet) {
3992d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3993450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
39949a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3995450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3996a3df083aSStefano Zampini         Mat    A_IIn;
3997a3df083aSStefano Zampini 
3998a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3999a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
4000a3df083aSStefano Zampini         pcis->A_II = A_IIn;
4001a3df083aSStefano Zampini       }
4002450f8f5eSStefano Zampini     }
40033301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
40043301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
4005964fefecSStefano Zampini     }
4006ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
4007964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
4008304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
4009304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
4010304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
4011304d26faSStefano Zampini       /* default */
4012304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
4013e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
40149577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
4015304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
40169577ea80SStefano Zampini       if (issbaij) {
40179577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
40189577ea80SStefano Zampini       } else {
4019304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
40209577ea80SStefano Zampini       }
4021304d26faSStefano Zampini       /* Allow user's customization */
4022304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
4023304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4024304d26faSStefano Zampini     }
4025d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
4026b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4027df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4028d62866d3SStefano Zampini 
4029df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
4030d5574798SStefano Zampini     }
4031304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4032304d26faSStefano Zampini     if (!n_D) {
4033304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
4034304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4035304d26faSStefano Zampini     }
4036304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
4037304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
4038304d26faSStefano Zampini     /* set ksp_D into pcis data */
4039304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
4040304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
4041304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
4042684f6988SStefano Zampini   }
4043304d26faSStefano Zampini 
4044304d26faSStefano Zampini   /* NEUMANN PROBLEM */
4045684f6988SStefano Zampini   A_RR = 0;
4046684f6988SStefano Zampini   if (neumann) {
4047d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
404804708bb6SStefano Zampini     PetscInt        ibs,mbs;
404904708bb6SStefano Zampini     PetscBool       issbaij;
405004708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
4051f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
40528ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
4053f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
4054f4ddd8eeSStefano Zampini       PetscInt nn_R;
405581d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
4056f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4057f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
4058f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
4059f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
4060f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4061f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4062f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
4063727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
4064f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4065f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
4066f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
4067f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
4068f4ddd8eeSStefano Zampini         }
4069f4ddd8eeSStefano Zampini       }
4070f4ddd8eeSStefano Zampini       /* last check */
4071d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
4072f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4073f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
4074f4ddd8eeSStefano Zampini       }
4075f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
4076f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
4077f4ddd8eeSStefano Zampini     }
4078a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
4079af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
4080af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
408104708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
408204708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
408304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
408404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
408504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
4086af732b37SStefano Zampini       } else {
4087511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
40886816873aSStefano Zampini       }
408904708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
409004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
409104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
409204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
409304708bb6SStefano Zampini       } else {
4094511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
409504708bb6SStefano Zampini       }
409604708bb6SStefano Zampini     }
4097a00504b5SStefano Zampini     /* extract A_RR */
4098b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4099a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4100a00504b5SStefano Zampini 
4101a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
410216e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4103a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
410416e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
410516e386b8SStefano Zampini         } else {
4106a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
4107a00504b5SStefano Zampini         }
4108a00504b5SStefano Zampini       } else {
4109a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4110a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
4111a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
4112a00504b5SStefano Zampini       }
4113a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
4114f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
411516e386b8SStefano Zampini     }
41163301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
41173301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
41186816873aSStefano Zampini     }
4119f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
4120304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
4121304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
4122304d26faSStefano Zampini       /* default */
4123304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
4124e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
4125304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
41269577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
41279577ea80SStefano Zampini       if (issbaij) {
41289577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
41299577ea80SStefano Zampini       } else {
4130304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
41319577ea80SStefano Zampini       }
4132304d26faSStefano Zampini       /* Allow user's customization */
4133304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
4134304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
4135304d26faSStefano Zampini     }
4136304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
4137304d26faSStefano Zampini     if (!n_R) {
4138304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
4139304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
4140304d26faSStefano Zampini     }
41415cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
4142df4d28bfSStefano Zampini     /* Reuse solver if it is present */
4143b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
4144df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4145d62866d3SStefano Zampini 
4146df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
4147d62866d3SStefano Zampini     }
4148304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
4149304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
4150684f6988SStefano Zampini   }
4151304d26faSStefano Zampini 
4152684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
4153684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
41541575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4155684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4156684f6988SStefano Zampini   }
4157c7017625SStefano Zampini 
4158c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
4159c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
4160c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
4161c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
4162c7017625SStefano Zampini   }
4163c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
4164c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
4165c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
4166c7017625SStefano Zampini   }
4167c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
4168c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
4169c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
4170c7017625SStefano Zampini   }
4171c7017625SStefano Zampini 
4172c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
4173c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
4174684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
41750fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
41760fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
41770fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
41780fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
41790fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
4180e604994aSStefano 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);
4181c7017625SStefano Zampini       if (check_corr[0]) {
4182c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
4183c7017625SStefano Zampini       }
4184304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4185304d26faSStefano Zampini     }
4186684f6988SStefano Zampini     if (neumann) { /* Neumann */
41870fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
41880fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
41890fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
41900fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
41910fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
4192e604994aSStefano 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);
4193c7017625SStefano Zampini       if (check_corr[1]) {
4194c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
4195c7017625SStefano Zampini       }
4196304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4197304d26faSStefano Zampini     }
4198684f6988SStefano Zampini   }
41995cbda25cSStefano Zampini   /* free Neumann problem's matrix */
42005cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
4201304d26faSStefano Zampini   PetscFunctionReturn(0);
4202304d26faSStefano Zampini }
4203304d26faSStefano Zampini 
4204304d26faSStefano Zampini #undef __FUNCT__
4205ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
420680677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
4207674ae819SStefano Zampini {
4208674ae819SStefano Zampini   PetscErrorCode  ierr;
4209674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4210be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4211b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
4212674ae819SStefano Zampini 
4213674ae819SStefano Zampini   PetscFunctionBegin;
4214b334f244SStefano Zampini   if (!reuse_solver) {
421580677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
421620c7b377SStefano Zampini   }
421780677318SStefano Zampini   if (!pcbddc->switch_static) {
421880677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
421980677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
422080677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
422120c7b377SStefano Zampini     }
4222b334f244SStefano Zampini     if (!reuse_solver) {
422380677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
422480677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
422520c7b377SStefano Zampini     } else {
4226df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4227be83ff47SStefano Zampini 
4228df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4229df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
423020c7b377SStefano Zampini     }
4231be83ff47SStefano Zampini   } else {
423280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
423380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
423480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
423580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
423680677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
423780677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
423880677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
423980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
424080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4241674ae819SStefano Zampini     }
4242674ae819SStefano Zampini   }
4243b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
424480677318SStefano Zampini     if (applytranspose) {
424580677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
424680677318SStefano Zampini     } else {
424780677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
424880677318SStefano Zampini     }
4249be83ff47SStefano Zampini   } else {
4250df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4251be83ff47SStefano Zampini 
4252be83ff47SStefano Zampini     if (applytranspose) {
4253df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4254be83ff47SStefano Zampini     } else {
4255df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
4256be83ff47SStefano Zampini     }
4257be83ff47SStefano Zampini   }
425880677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
425980677318SStefano Zampini   if (!pcbddc->switch_static) {
4260b334f244SStefano Zampini     if (!reuse_solver) {
426180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
426280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4263be83ff47SStefano Zampini     } else {
4264df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
4265be83ff47SStefano Zampini 
4266df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4267df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4268be83ff47SStefano Zampini     }
426980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
427080677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
427180677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
427280677318SStefano Zampini     }
427380677318SStefano Zampini   } else {
427480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
427880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
427980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
428080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
428180677318SStefano Zampini     }
428280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
428380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
428480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
428580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4286674ae819SStefano Zampini   }
4287674ae819SStefano Zampini   PetscFunctionReturn(0);
4288674ae819SStefano Zampini }
4289674ae819SStefano Zampini 
4290dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
4291674ae819SStefano Zampini #undef __FUNCT__
4292674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
4293dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
4294674ae819SStefano Zampini {
4295674ae819SStefano Zampini   PetscErrorCode ierr;
4296674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4297674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
4298674ae819SStefano Zampini   const PetscScalar zero = 0.0;
4299674ae819SStefano Zampini 
4300674ae819SStefano Zampini   PetscFunctionBegin;
4301dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
43024fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4303dc359a40SStefano Zampini     if (applytranspose) {
4304674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
43058eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4306dc359a40SStefano Zampini     } else {
4307674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4308674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
430915aaf578SStefano Zampini     }
43104fee134fSStefano Zampini   } else {
43114fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
43124fee134fSStefano Zampini   }
4313efc2fbd9SStefano Zampini 
4314efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
43154f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
4316efc2fbd9SStefano Zampini     PetscScalar *array;
43174f1b2e48SStefano Zampini     PetscInt    j;
4318efc2fbd9SStefano Zampini 
4319efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
43204f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
4321efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4322efc2fbd9SStefano Zampini   }
4323efc2fbd9SStefano Zampini 
432412edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
432512edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
432612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
432712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
432812edc857SStefano Zampini 
43299f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
433012edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
433151694757SStefano Zampini     Mat          coarse_mat;
4332964fefecSStefano Zampini     Vec          rhs,sol;
433351694757SStefano Zampini     MatNullSpace nullsp;
433427b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
4335964fefecSStefano Zampini 
433627b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
433727b6a85dSStefano Zampini       PC        coarse_pc;
433827b6a85dSStefano Zampini 
433927b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
434027b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
434127b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
434227b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
434327b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
434427b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
43453bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
434627b6a85dSStefano Zampini       }
434727b6a85dSStefano Zampini     }
4348964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
4349964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
435051694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
435151694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
435251694757SStefano Zampini     if (nullsp) {
435351694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
435451694757SStefano Zampini     }
435512edc857SStefano Zampini     if (applytranspose) {
43569a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
4357964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
43582701bc32SStefano Zampini     } else {
43591f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
43602701bc32SStefano Zampini         PC        coarse_pc;
43612701bc32SStefano Zampini 
43622701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
43632701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
43643e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
43652701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
436612edc857SStefano Zampini       } else {
4367964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
436812edc857SStefano Zampini       }
43692701bc32SStefano Zampini     }
43701d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
437127b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
437227b6a85dSStefano Zampini       PC        coarse_pc;
437327b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
437427b6a85dSStefano Zampini 
437527b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
437627b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
437727b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
43783bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
437927b6a85dSStefano Zampini     }
438051694757SStefano Zampini     if (nullsp) {
438151694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
438251694757SStefano Zampini     }
438312edc857SStefano Zampini   }
4384674ae819SStefano Zampini 
4385674ae819SStefano Zampini   /* Local solution on R nodes */
43864fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
438780677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
43889f00e9b4SStefano Zampini   }
43899f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
43909f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
439112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4392674ae819SStefano Zampini 
43934fee134fSStefano Zampini   /* Sum contributions from the two levels */
43944fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
4395dc359a40SStefano Zampini     if (applytranspose) {
4396dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4397dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4398dc359a40SStefano Zampini     } else {
4399674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
44008eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4401dc359a40SStefano Zampini     }
4402efc2fbd9SStefano Zampini     /* store p0 */
44034f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
4404efc2fbd9SStefano Zampini       PetscScalar *array;
44054f1b2e48SStefano Zampini       PetscInt    j;
4406efc2fbd9SStefano Zampini 
4407efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
44084f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
4409efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
4410efc2fbd9SStefano Zampini     }
44114fee134fSStefano Zampini   } else { /* expand the coarse solution */
44124fee134fSStefano Zampini     if (applytranspose) {
44134fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
44144fee134fSStefano Zampini     } else {
44154fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
44164fee134fSStefano Zampini     }
44174fee134fSStefano Zampini   }
4418674ae819SStefano Zampini   PetscFunctionReturn(0);
4419674ae819SStefano Zampini }
4420674ae819SStefano Zampini 
4421674ae819SStefano Zampini #undef __FUNCT__
4422674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
442312edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
4424674ae819SStefano Zampini {
4425674ae819SStefano Zampini   PetscErrorCode ierr;
4426674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
442758da7f69SStefano Zampini   PetscScalar    *array;
442812edc857SStefano Zampini   Vec            from,to;
4429674ae819SStefano Zampini 
4430674ae819SStefano Zampini   PetscFunctionBegin;
443112edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
443212edc857SStefano Zampini     from = pcbddc->coarse_vec;
443312edc857SStefano Zampini     to = pcbddc->vec1_P;
443412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
443512edc857SStefano Zampini       Vec tvec;
443658da7f69SStefano Zampini 
443758da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
443858da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
443912edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
444058da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
444158da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
444258da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
444312edc857SStefano Zampini     }
444412edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
444512edc857SStefano Zampini     from = pcbddc->vec1_P;
444612edc857SStefano Zampini     to = pcbddc->coarse_vec;
444712edc857SStefano Zampini   }
444812edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
4449674ae819SStefano Zampini   PetscFunctionReturn(0);
4450674ae819SStefano Zampini }
4451674ae819SStefano Zampini 
4452674ae819SStefano Zampini #undef __FUNCT__
4453674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
445412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
4455674ae819SStefano Zampini {
4456674ae819SStefano Zampini   PetscErrorCode ierr;
4457674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
445858da7f69SStefano Zampini   PetscScalar    *array;
445912edc857SStefano Zampini   Vec            from,to;
4460674ae819SStefano Zampini 
4461674ae819SStefano Zampini   PetscFunctionBegin;
446212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
446312edc857SStefano Zampini     from = pcbddc->coarse_vec;
446412edc857SStefano Zampini     to = pcbddc->vec1_P;
446512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
446612edc857SStefano Zampini     from = pcbddc->vec1_P;
446712edc857SStefano Zampini     to = pcbddc->coarse_vec;
446812edc857SStefano Zampini   }
446912edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
447012edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
447112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
447212edc857SStefano Zampini       Vec tvec;
447358da7f69SStefano Zampini 
447412edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
447558da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
447658da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
447758da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
447858da7f69SStefano Zampini     }
447958da7f69SStefano Zampini   } else {
448058da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
448158da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
448212edc857SStefano Zampini     }
448312edc857SStefano Zampini   }
4484674ae819SStefano Zampini   PetscFunctionReturn(0);
4485674ae819SStefano Zampini }
4486674ae819SStefano Zampini 
4487984c4197SStefano Zampini /* uncomment for testing purposes */
4488984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
4489674ae819SStefano Zampini #undef __FUNCT__
4490674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
4491674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
4492674ae819SStefano Zampini {
4493674ae819SStefano Zampini   PetscErrorCode    ierr;
4494674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
4495674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
4496674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
4497984c4197SStefano Zampini   /* one and zero */
4498984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
4499984c4197SStefano Zampini   /* space to store constraints and their local indices */
45009162d606SStefano Zampini   PetscScalar       *constraints_data;
45019162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
45029162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
45039162d606SStefano Zampini   PetscInt          *constraints_n;
4504984c4197SStefano Zampini   /* iterators */
4505b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
4506984c4197SStefano Zampini   /* BLAS integers */
4507e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
4508e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
4509c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
4510727cdba6SStefano Zampini   /* reuse */
45110e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
45120e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
4513984c4197SStefano Zampini   /* change of basis */
4514b3d85658SStefano Zampini   PetscBool         qr_needed;
45159162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
4516984c4197SStefano Zampini   /* auxiliary stuff */
451764efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
45188a0068c3SStefano Zampini   PetscInt          ncc;
4519984c4197SStefano Zampini   /* some quantities */
452045a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
4521a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
4522984c4197SStefano Zampini 
4523674ae819SStefano Zampini   PetscFunctionBegin;
45248e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
45258e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
45268e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
452716909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
4528088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
4529088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
45300e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
45310e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
45320e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
45330e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
45340e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
4535088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4536cf5a6209SStefano Zampini 
4537cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
45389162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
4539cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
4540cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
4541cf5a6209SStefano Zampini     Vec          *localnearnullsp;
4542cf5a6209SStefano Zampini     PetscScalar  *array;
4543cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
4544cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
4545674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
4546b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
4547674ae819SStefano Zampini     PetscScalar  *work;
4548674ae819SStefano Zampini     PetscReal    *singular_vals;
4549674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4550674ae819SStefano Zampini     PetscReal    *rwork;
4551674ae819SStefano Zampini #endif
4552674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4553674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
4554674ae819SStefano Zampini #else
4555964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
4556964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
4557674ae819SStefano Zampini #endif
4558674ae819SStefano Zampini 
4559674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
4560d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
4561e4d548c7SStefano Zampini     /* print some info */
45621f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
4563e4d548c7SStefano Zampini       PetscInt nv;
4564e4d548c7SStefano Zampini 
4565c8272957SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4566e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
4567e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4568e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4569e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
4570e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
4571e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
4572e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4573e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
4574e4d548c7SStefano Zampini     }
4575e4d548c7SStefano Zampini 
4576d06fc5fdSStefano Zampini     /* free unneeded index sets */
4577d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
4578d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
4579674ae819SStefano Zampini     }
4580d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
4581d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
4582d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4583d06fc5fdSStefano Zampini       }
4584d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4585d06fc5fdSStefano Zampini       n_ISForEdges = 0;
4586d06fc5fdSStefano Zampini     }
4587d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
4588d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
4589d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4590d06fc5fdSStefano Zampini       }
4591d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4592d06fc5fdSStefano Zampini       n_ISForFaces = 0;
4593d06fc5fdSStefano Zampini     }
459470022509SStefano Zampini 
4595674ae819SStefano Zampini     /* check if near null space is attached to global mat */
4596674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
4597674ae819SStefano Zampini     if (nearnullsp) {
4598674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
4599f4ddd8eeSStefano Zampini       /* remove any stored info */
4600f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
4601f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4602f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
4603f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
4604f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
4605473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
4606f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
4607f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
4608f4ddd8eeSStefano Zampini       }
4609984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
4610984c4197SStefano Zampini       nnsp_size = 0;
4611674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
4612674ae819SStefano Zampini     }
4613984c4197SStefano Zampini     /* get max number of constraints on a single cc */
4614984c4197SStefano Zampini     max_constraints = nnsp_size;
4615984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
4616984c4197SStefano Zampini 
4617674ae819SStefano Zampini     /*
4618674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
46199162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
46209162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
46219162d606SStefano Zampini          There can be multiple constraints per connected component
4622674ae819SStefano Zampini                                                                                                                                                            */
4623674ae819SStefano Zampini     n_vertices = 0;
4624674ae819SStefano Zampini     if (ISForVertices) {
4625674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
4626674ae819SStefano Zampini     }
46279162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
46289162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
46299162d606SStefano Zampini 
46309162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
46319162d606SStefano Zampini     total_counts *= max_constraints;
4632674ae819SStefano Zampini     total_counts += n_vertices;
46334641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
46349162d606SStefano Zampini 
4635674ae819SStefano Zampini     total_counts = 0;
4636674ae819SStefano Zampini     max_size_of_constraint = 0;
4637674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
46389162d606SStefano Zampini       IS used_is;
4639674ae819SStefano Zampini       if (i<n_ISForEdges) {
46409162d606SStefano Zampini         used_is = ISForEdges[i];
4641674ae819SStefano Zampini       } else {
46429162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
4643674ae819SStefano Zampini       }
46449162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
4645674ae819SStefano Zampini       total_counts += j;
4646674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
4647674ae819SStefano Zampini     }
46489162d606SStefano 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);
46499162d606SStefano Zampini 
4650984c4197SStefano Zampini     /* get local part of global near null space vectors */
4651785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
4652984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4653984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
4654e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4655e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4656984c4197SStefano Zampini     }
4657674ae819SStefano Zampini 
4658242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
4659242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
4660a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
4661242a89d7SStefano Zampini 
4662984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
4663a773dcb8SStefano Zampini     if (!skip_lapack) {
4664674ae819SStefano Zampini       PetscScalar temp_work;
4665911cabfeSStefano Zampini 
4666674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4667984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
4668785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
4669785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
4670785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
4671674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4672785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
4673674ae819SStefano Zampini #endif
4674674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4675c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
4676c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
4677674ae819SStefano Zampini       lwork = -1;
4678674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4679674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4680c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
4681674ae819SStefano Zampini #else
4682c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
4683674ae819SStefano Zampini #endif
4684674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4685984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
4686674ae819SStefano Zampini #else /* on missing GESVD */
4687674ae819SStefano Zampini       /* SVD */
4688674ae819SStefano Zampini       PetscInt max_n,min_n;
4689674ae819SStefano Zampini       max_n = max_size_of_constraint;
4690984c4197SStefano Zampini       min_n = max_constraints;
4691984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
4692674ae819SStefano Zampini         min_n = max_size_of_constraint;
4693984c4197SStefano Zampini         max_n = max_constraints;
4694674ae819SStefano Zampini       }
4695785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
4696674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4697785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
4698674ae819SStefano Zampini #endif
4699674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
4700674ae819SStefano Zampini       lwork = -1;
4701e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
4702e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
4703b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
4704674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4705674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
47069162d606SStefano 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));
4707674ae819SStefano Zampini #else
47089162d606SStefano 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));
4709674ae819SStefano Zampini #endif
4710674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
4711984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
4712984c4197SStefano Zampini #endif /* on missing GESVD */
4713674ae819SStefano Zampini       /* Allocate optimal workspace */
4714674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
4715854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
4716674ae819SStefano Zampini     }
4717674ae819SStefano Zampini     /* Now we can loop on constraining sets */
4718674ae819SStefano Zampini     total_counts = 0;
47199162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
47209162d606SStefano Zampini     constraints_data_ptr[0] = 0;
4721674ae819SStefano Zampini     /* vertices */
47229162d606SStefano Zampini     if (n_vertices) {
4723674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
47249162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
4725674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
47269162d606SStefano Zampini         constraints_n[total_counts] = 1;
47279162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
47289162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
47299162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
4730674ae819SStefano Zampini         total_counts++;
4731674ae819SStefano Zampini       }
4732674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4733674ae819SStefano Zampini       n_vertices = total_counts;
4734674ae819SStefano Zampini     }
4735984c4197SStefano Zampini 
4736674ae819SStefano Zampini     /* edges and faces */
47379162d606SStefano Zampini     total_counts_cc = total_counts;
4738911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
47399162d606SStefano Zampini       IS        used_is;
47409162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
47419162d606SStefano Zampini 
4742911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
47439162d606SStefano Zampini         used_is = ISForEdges[ncc];
4744984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
4745674ae819SStefano Zampini       } else {
47469162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
4747984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
4748674ae819SStefano Zampini       }
4749674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
47509162d606SStefano Zampini 
47519162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
47529162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4753984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
4754984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
4755674ae819SStefano Zampini       if (nnsp_has_cnst) {
47565b08dc53SStefano Zampini         PetscScalar quad_value;
47579162d606SStefano Zampini 
47589162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
47599162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
47609162d606SStefano Zampini 
4761a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
4762674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
4763a773dcb8SStefano Zampini         } else {
4764a773dcb8SStefano Zampini           quad_value = 1.0;
4765a773dcb8SStefano Zampini         }
4766674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
47679162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
4768674ae819SStefano Zampini         }
47699162d606SStefano Zampini         temp_constraints++;
4770674ae819SStefano Zampini         total_counts++;
4771674ae819SStefano Zampini       }
4772674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
4773984c4197SStefano Zampini         PetscReal real_value;
47749162d606SStefano Zampini         PetscScalar *ptr_to_data;
47759162d606SStefano Zampini 
4776984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
47779162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
4778674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
47799162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
4780674ae819SStefano Zampini         }
4781984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
4782984c4197SStefano Zampini         /* check if array is null on the connected component */
4783e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
47849162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
47855b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
4786674ae819SStefano Zampini           temp_constraints++;
4787674ae819SStefano Zampini           total_counts++;
47889162d606SStefano Zampini           if (!idxs_copied) {
47899162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
47909162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
4791674ae819SStefano Zampini           }
4792674ae819SStefano Zampini         }
47939162d606SStefano Zampini       }
47949162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
479545a1bb75SStefano Zampini       valid_constraints = temp_constraints;
4796eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
4797a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
47989162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
47999162d606SStefano Zampini 
48009162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4801a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
48029162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
4803a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
48049162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
4805a773dcb8SStefano Zampini         } else { /* perform SVD */
4806984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
48079162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
4808674ae819SStefano Zampini 
4809674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4810984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
4811984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
4812984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
4813984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
4814984c4197SStefano Zampini                 from that computed using LAPACKgesvd
4815984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
4816984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
4817984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
4818674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
4819e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4820984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4821674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
4822674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
48239162d606SStefano 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));
4824674ae819SStefano Zampini             }
4825674ae819SStefano Zampini           }
4826e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
4827e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4828e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
4829674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
4830c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
4831674ae819SStefano Zampini #else
4832c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
4833674ae819SStefano Zampini #endif
4834674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4835984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
4836984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
4837674ae819SStefano Zampini           j = 0;
4838984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
4839674ae819SStefano Zampini           total_counts = total_counts-j;
484045a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
4841e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
4842c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
4843c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4844c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
4845c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4846c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
4847c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4848674ae819SStefano Zampini           if (j<temp_constraints) {
4849984c4197SStefano Zampini             PetscInt ii;
4850984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
4851674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
48529162d606SStefano 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));
4853674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4854984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
4855674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
48569162d606SStefano 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];
4857674ae819SStefano Zampini               }
4858674ae819SStefano Zampini             }
4859674ae819SStefano Zampini           }
4860674ae819SStefano Zampini #else  /* on missing GESVD */
4861e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
4862e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4863b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4864674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4865674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
48669162d606SStefano 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));
4867674ae819SStefano Zampini #else
48689162d606SStefano 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));
4869674ae819SStefano Zampini #endif
4870984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
4871674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4872984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
4873e310c8b4SStefano Zampini           k = temp_constraints;
4874e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
4875674ae819SStefano Zampini           j = 0;
4876e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
487745a1bb75SStefano Zampini           valid_constraints = k-j;
4878911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
4879984c4197SStefano Zampini #endif /* on missing GESVD */
4880674ae819SStefano Zampini         }
4881a773dcb8SStefano Zampini       }
48829162d606SStefano Zampini       /* update pointers information */
48839162d606SStefano Zampini       if (valid_constraints) {
48849162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
48859162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
48869162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
48879162d606SStefano Zampini         /* set change_of_basis flag */
488845a1bb75SStefano Zampini         if (boolforchange) {
4889b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
48909162d606SStefano Zampini         }
4891b3d85658SStefano Zampini         total_counts_cc++;
489245a1bb75SStefano Zampini       }
489345a1bb75SStefano Zampini     }
4894984c4197SStefano Zampini     /* free workspace */
48958f1c130eSStefano Zampini     if (!skip_lapack) {
4896984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
4897984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4898984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
4899984c4197SStefano Zampini #endif
4900984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
4901984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4902984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
4903984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
4904984c4197SStefano Zampini #endif
4905984c4197SStefano Zampini     }
4906984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4907984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
4908984c4197SStefano Zampini     }
4909984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
4910cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
4911cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
4912cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4913cf5a6209SStefano Zampini     }
4914cf5a6209SStefano Zampini     if (n_ISForFaces) {
4915cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4916cf5a6209SStefano Zampini     }
4917cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
4918cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4919cf5a6209SStefano Zampini     }
4920cf5a6209SStefano Zampini     if (n_ISForEdges) {
4921cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4922cf5a6209SStefano Zampini     }
4923cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
492408122e43SStefano Zampini   } else {
492508122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4926984c4197SStefano Zampini 
492708122e43SStefano Zampini     total_counts = 0;
492808122e43SStefano Zampini     n_vertices = 0;
4929d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
4930d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
493108122e43SStefano Zampini     }
493208122e43SStefano Zampini     max_constraints = 0;
49339162d606SStefano Zampini     total_counts_cc = 0;
493408122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
493508122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
49369162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
493708122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
493808122e43SStefano Zampini     }
49399162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
49409162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
49419162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
49429162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
494374d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
49449162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
49459162d606SStefano Zampini     total_counts_cc = 0;
49469162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
49479162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
49489162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
494908122e43SStefano Zampini       }
495008122e43SStefano Zampini     }
49519162d606SStefano Zampini #if 0
49529162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
49539162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
49549162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
49559162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
49569162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
49579162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
49589162d606SStefano Zampini       }
49599162d606SStefano Zampini       printf("\n");
49609162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
49619162d606SStefano Zampini     }
49621b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
49638bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
49641b968477SStefano Zampini     }
49651b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
49668bec7fa6SStefano 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]);
49671b968477SStefano Zampini     }
496808122e43SStefano Zampini #endif
496908122e43SStefano Zampini 
49708bec7fa6SStefano Zampini     max_size_of_constraint = 0;
49719162d606SStefano 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]);
49729162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
497308122e43SStefano Zampini     /* Change of basis */
4974b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
497508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
497608122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
497708122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4978b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
497908122e43SStefano Zampini         }
498008122e43SStefano Zampini       }
498108122e43SStefano Zampini     }
498208122e43SStefano Zampini   }
4983984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
49844f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
498508122e43SStefano Zampini 
49869162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
49879162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
49886c4ed002SBarry 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);
4989674ae819SStefano Zampini 
4990674ae819SStefano Zampini   /* Create constraint matrix */
4991674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
499216f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4993984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4994984c4197SStefano Zampini 
4995984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4996a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4997a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
499874d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4999984c4197SStefano Zampini   total_primal_vertices=0;
5000b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
50019162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
50029162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
500372b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
50049162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
5005b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
500664efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
50079162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
50089162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
5009a717540cSStefano Zampini       }
5010b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
501191af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
5012a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
5013a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
5014a717540cSStefano Zampini       }
5015fa434743SStefano Zampini     } else {
5016b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
5017fa434743SStefano Zampini     }
5018a717540cSStefano Zampini   }
5019b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
5020b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
5021674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
502270022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
5023b3d85658SStefano Zampini 
50244f1b2e48SStefano 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);
50250e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
50260e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
5027984c4197SStefano Zampini 
5028984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
502974d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
5030785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
5031984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
503274d5cdf7SStefano Zampini 
5033984c4197SStefano Zampini   j = total_primal_vertices;
503474d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
5035b3d85658SStefano Zampini   cum = total_primal_vertices;
50369162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
50374641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
5038b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
5039b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
5040b3d85658SStefano Zampini       cum++;
50419162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
504274d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
504374d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
504474d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
504574d5cdf7SStefano Zampini       }
50469162d606SStefano Zampini       j += constraints_n[i];
5047674ae819SStefano Zampini     }
5048674ae819SStefano Zampini   }
5049674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
5050674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
5051088faed8SStefano Zampini 
5052674ae819SStefano Zampini   /* set values in constraint matrix */
5053984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
50540e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5055674ae819SStefano Zampini   }
5056984c4197SStefano Zampini   total_counts = total_primal_vertices;
50579162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
50584641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
50599162d606SStefano Zampini       PetscInt *cols;
50609162d606SStefano Zampini 
50619162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
50629162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
50639162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
50649162d606SStefano Zampini         PetscInt    row = total_counts+k;
50659162d606SStefano Zampini         PetscScalar *vals;
50669162d606SStefano Zampini 
50679162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
50689162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
50699162d606SStefano Zampini       }
50709162d606SStefano Zampini       total_counts += constraints_n[i];
5071674ae819SStefano Zampini     }
5072674ae819SStefano Zampini   }
5073674ae819SStefano Zampini   /* assembling */
5074674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5075674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5076088faed8SStefano Zampini 
5077984c4197SStefano Zampini   /*
50786a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5079984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
5080f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
5081984c4197SStefano Zampini   */
5082674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
5083674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
5084026de310SStefano Zampini     /* dual and primal dofs on a single cc */
5085984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
5086984c4197SStefano Zampini     /* working stuff for GEQRF */
508781d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
5088984c4197SStefano Zampini     PetscBLASInt lqr_work;
5089984c4197SStefano Zampini     /* working stuff for UNGQR */
5090984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
5091984c4197SStefano Zampini     PetscBLASInt lgqr_work;
5092984c4197SStefano Zampini     /* working stuff for TRTRS */
5093984c4197SStefano Zampini     PetscScalar  *trs_rhs;
50943f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
5095984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
5096984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
5097984c4197SStefano Zampini     PetscScalar  *start_vals;
5098984c4197SStefano Zampini     /* working stuff for values insertion */
50994641a718SStefano Zampini     PetscBT      is_primal;
510064efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
5101906d46d4SStefano Zampini     /* matrix sizes */
5102906d46d4SStefano Zampini     PetscInt     global_size,local_size;
5103906d46d4SStefano Zampini     /* temporary change of basis */
5104906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
5105cf5a6209SStefano Zampini     /* extra space for debugging */
5106cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
5107984c4197SStefano Zampini 
5108906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
5109906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
511016f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
5111bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
5112906d46d4SStefano Zampini     /* nonzeros for local mat */
5113bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
51141dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5115bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
51161dd7afcfSStefano Zampini     } else {
51171dd7afcfSStefano Zampini       const PetscInt *ii;
51181dd7afcfSStefano Zampini       PetscInt       n;
51191dd7afcfSStefano Zampini       PetscBool      flg_row;
51201dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
51211dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
51221dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
51231dd7afcfSStefano Zampini     }
51249162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
5125a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
51269162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
5127a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
51289162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
5129a717540cSStefano Zampini         } else {
51309162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
51319162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
5132a717540cSStefano Zampini         }
5133a717540cSStefano Zampini       }
5134a717540cSStefano Zampini     }
5135906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
5136bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
51371dd7afcfSStefano Zampini     /* Set interior change in the matrix */
51381dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
5139bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
5140906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5141a717540cSStefano Zampini       }
51421dd7afcfSStefano Zampini     } else {
51431dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
51441dd7afcfSStefano Zampini       PetscScalar    *aa;
51451dd7afcfSStefano Zampini       PetscInt       n;
51461dd7afcfSStefano Zampini       PetscBool      flg_row;
51471dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
51481dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
51491dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
51501dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
51511dd7afcfSStefano Zampini       }
51521dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
51531dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
51541dd7afcfSStefano Zampini     }
5155a717540cSStefano Zampini 
5156a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
5157a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5158a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5159a717540cSStefano Zampini     }
5160a717540cSStefano Zampini 
5161a717540cSStefano Zampini 
5162a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
5163a717540cSStefano Zampini     /*
5164a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
5165a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
5166a717540cSStefano Zampini 
5167a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
5168a717540cSStefano Zampini 
5169a6b551f4SStefano 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)
5170a6b551f4SStefano Zampini 
5171a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
5172a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
5173a717540cSStefano Zampini             |              ...                        |
5174a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
5175a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
5176a717540cSStefano Zampini 
5177a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
5178a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
5179a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
5180a6b551f4SStefano Zampini 
5181a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
5182a717540cSStefano Zampini     */
5183a717540cSStefano Zampini     if (qr_needed) {
5184984c4197SStefano Zampini       /* space to store Q */
5185854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
51864e64d54eSstefano_zampini       /* array to store scaling factors for reflectors */
51874e64d54eSstefano_zampini       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
5188984c4197SStefano Zampini       /* first we issue queries for optimal work */
51893f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
51903f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
51913f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5192984c4197SStefano Zampini       lqr_work = -1;
51933f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
5194984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
5195984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
5196785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
5197984c4197SStefano Zampini       lgqr_work = -1;
51983f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
51993f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
52003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
52013f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
52023f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
52033f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
5204984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
5205984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
5206785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
5207984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
5208785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
5209a717540cSStefano Zampini       /* allocating workspace for check */
5210a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
5211cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
5212a717540cSStefano Zampini       }
5213a717540cSStefano Zampini     }
5214984c4197SStefano Zampini     /* array to store whether a node is primal or not */
52154641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
5216473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
52170e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
52186c4ed002SBarry 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);
521939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
522039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
522139e2fb2aSStefano Zampini     }
522239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
5223984c4197SStefano Zampini 
5224a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
52259162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
52269162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
52274641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
5228984c4197SStefano Zampini         /* get constraint info */
52299162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
5230984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
5231984c4197SStefano Zampini 
5232984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
52339162d606SStefano 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);
5234674ae819SStefano Zampini         }
5235984c4197SStefano Zampini 
5236fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
5237a717540cSStefano Zampini 
5238a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
5239a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
52409162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5241a717540cSStefano Zampini           }
5242984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
52439162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5244984c4197SStefano Zampini 
5245984c4197SStefano Zampini           /* compute QR decomposition of constraints */
52463f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52473f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52483f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5249674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52503f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
5251984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
5252674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5253984c4197SStefano Zampini 
5254984c4197SStefano Zampini           /* explictly compute R^-T */
5255984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
5256984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
52573f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52583f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
52593f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
52603f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
5261984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52623f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
5263984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
5264984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5265984c4197SStefano Zampini 
5266a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
52673f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52683f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
52693f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
52703f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5271984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52723f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
5273984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
5274984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
5275984c4197SStefano Zampini 
5276984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
5277984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
5278984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
52793f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
52803f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
52813f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
52823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
52833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
52843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
5285984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
52869162d606SStefano 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));
5287984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
52889162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
5289984c4197SStefano Zampini 
5290984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
52919162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
5292984c4197SStefano Zampini           /* insert cols for primal dofs */
5293984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
5294984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
52959162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5296906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5297984c4197SStefano Zampini           }
5298984c4197SStefano Zampini           /* insert cols for dual dofs */
5299984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
53009162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
5301984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
53029162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5303906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
5304984c4197SStefano Zampini               j++;
5305674ae819SStefano Zampini             }
5306674ae819SStefano Zampini           }
5307984c4197SStefano Zampini 
5308984c4197SStefano Zampini           /* check change of basis */
5309984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
5310984c4197SStefano Zampini             PetscInt   ii,jj;
5311984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
5312c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
5313c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
5314c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
5315c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
5316c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
5317c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
5318984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
5319cf5a6209SStefano 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));
5320984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
5321984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
5322984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
5323cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
5324cf5a6209SStefano 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;
5325674ae819SStefano Zampini               }
5326674ae819SStefano Zampini             }
5327984c4197SStefano Zampini             if (!valid_qr) {
532822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
5329984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
5330984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
5331cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
5332cf5a6209SStefano 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]));
5333674ae819SStefano Zampini                   }
5334cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
5335cf5a6209SStefano 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]));
5336984c4197SStefano Zampini                   }
5337984c4197SStefano Zampini                 }
5338984c4197SStefano Zampini               }
5339674ae819SStefano Zampini             } else {
534022d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
5341674ae819SStefano Zampini             }
5342674ae819SStefano Zampini           }
5343a717540cSStefano Zampini         } else { /* simple transformation block */
5344a717540cSStefano Zampini           PetscInt    row,col;
5345a6b551f4SStefano Zampini           PetscScalar val,norm;
5346a6b551f4SStefano Zampini 
5347a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
53489162d606SStefano 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));
5349a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
53509162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
53519162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
5352bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
53539162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
5354906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
53559162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
5356a717540cSStefano Zampini             } else {
5357a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
53589162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
5359a717540cSStefano Zampini                 if (row != col) {
53609162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
5361a717540cSStefano Zampini                 } else {
53629162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
5363a717540cSStefano Zampini                 }
5364906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
5365a717540cSStefano Zampini               }
5366a717540cSStefano Zampini             }
5367a717540cSStefano Zampini           }
536898a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
536922d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
5370a717540cSStefano Zampini           }
5371674ae819SStefano Zampini         }
5372984c4197SStefano Zampini       } else {
5373984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
53749162d606SStefano 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);
5375674ae819SStefano Zampini         }
5376674ae819SStefano Zampini       }
5377674ae819SStefano Zampini     }
5378a717540cSStefano Zampini 
5379a717540cSStefano Zampini     /* free workspace */
5380a717540cSStefano Zampini     if (qr_needed) {
5381984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
5382cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
5383984c4197SStefano Zampini       }
5384984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
5385984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
5386984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
5387984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
5388984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
5389674ae819SStefano Zampini     }
5390a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
5391906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5392906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5393906d46d4SStefano Zampini 
5394906d46d4SStefano Zampini     /* assembling of global change of variable */
539588c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
5396bbb9e6c6SStefano Zampini       Mat      tmat;
539716f15bc4SStefano Zampini       PetscInt bs;
539816f15bc4SStefano Zampini 
5399906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
5400906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
5401bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
5402bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
5403bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5404bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
540516f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
540616f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
5407906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
5408bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
5409bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
5410bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5411bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5412bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5413e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5414e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5415bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
5416bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
541788c03ad3SStefano Zampini 
5418906d46d4SStefano Zampini       /* check */
5419906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
5420906d46d4SStefano Zampini         PetscReal error;
5421906d46d4SStefano Zampini         Vec       x,x_change;
5422906d46d4SStefano Zampini 
5423906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
5424906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
5425906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
5426906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
5427e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5428e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5429bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
5430e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5431e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5432906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
5433906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
5434906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
5435906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5436bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
5437906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
5438906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
5439906d46d4SStefano Zampini       }
5440b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
5441b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
5442b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
5443bf3a8328SStefano Zampini 
54449a962809SStefano 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);
5445b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
5446ac632422SStefano Zampini           Mat                    S_new,tmat;
5447bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
5448bbb9e6c6SStefano Zampini 
5449bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
54506816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
5451bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5452bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
5453bf3a8328SStefano Zampini             IS                     is_V;
5454b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
5455b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
5456b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
5457b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
5458b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
5459bf3a8328SStefano Zampini           }
5460bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
5461ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5462b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
5463ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5464bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
5465bf3a8328SStefano Zampini             const PetscScalar *array;
5466bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
5467bf3a8328SStefano Zampini             PetscInt          i,n_V;
5468bf3a8328SStefano Zampini 
5469b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5470b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
5471b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5472b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5473b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
5474b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
5475b087196eSStefano Zampini               PetscScalar val;
5476b087196eSStefano Zampini               PetscInt    idx;
5477b087196eSStefano Zampini 
5478b087196eSStefano Zampini               idx = idxs_V[i];
5479b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
5480b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
5481b087196eSStefano Zampini             }
5482b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5483b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5484bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
5485bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
5486bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
5487bf3a8328SStefano Zampini           }
5488ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
5489ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5490ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
5491ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
5492b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
5493ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
5494bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
5495b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
5496bf3a8328SStefano Zampini             }
5497ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
5498ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
5499ac632422SStefano Zampini           }
5500b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
550188c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
5502b96c3477SStefano Zampini         }
5503c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
5504b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
5505c9db6a07SStefano Zampini           PetscInt i;
5506c9db6a07SStefano Zampini 
5507c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
5508c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
5509c9db6a07SStefano Zampini           }
5510c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
5511c9db6a07SStefano Zampini         }
5512b96c3477SStefano Zampini       }
551316909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
551416909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
551516909a7fSStefano Zampini       } else {
5516906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
551716909a7fSStefano Zampini       }
55181dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
551927b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
552072b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
552172b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
552272b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
552372b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
552472b8c272SStefano Zampini     }
55251dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
552627b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
5527b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
5528b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
5529906d46d4SStefano Zampini     } else {
55301dd7afcfSStefano Zampini       Mat benign_global = NULL;
553127b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
55321dd7afcfSStefano Zampini         Mat tmat;
55331dd7afcfSStefano Zampini 
55341dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
55351dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
55361dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
55371dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
55381dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
55391dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
55401dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
55411dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
55421dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
55431dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
55441dd7afcfSStefano Zampini           Mat M;
55451dd7afcfSStefano Zampini 
55461dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
55471dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
55481dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
55491dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
5550906d46d4SStefano Zampini         } else {
55511dd7afcfSStefano Zampini           Mat         eye;
55521dd7afcfSStefano Zampini           PetscScalar *array;
55531dd7afcfSStefano Zampini 
55541dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
55551dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
55561dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
55571dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
5558906d46d4SStefano Zampini           }
55591dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
55601dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55611dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55621dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
55631dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
55641dd7afcfSStefano Zampini         }
55651dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
55661dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
55671dd7afcfSStefano Zampini       }
55681dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
55691dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
55701dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
557127b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
55721dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
55731dd7afcfSStefano Zampini       }
55741dd7afcfSStefano Zampini     }
557516909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
557616909a7fSStefano Zampini       IS             is_global;
557716909a7fSStefano Zampini       const PetscInt *gidxs;
557816909a7fSStefano Zampini 
557916909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
558016909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
558116909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
558216909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
558316909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
558416909a7fSStefano Zampini     }
55851dd7afcfSStefano Zampini   }
55861dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
55871dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
5588b9b85e73SStefano Zampini   }
5589a717540cSStefano Zampini 
559072b8c272SStefano Zampini   if (!pcbddc->fake_change) {
55914f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
55924f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
55934f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
55944f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
5595019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
5596019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
5597019a44ceSStefano Zampini       pcbddc->local_primal_size++;
5598019a44ceSStefano Zampini     }
5599019a44ceSStefano Zampini 
5600019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
5601727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
5602727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
56039f47a83aSStefano 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);
5604c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
56050e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
56069f47a83aSStefano 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);
5607727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
5608727cdba6SStefano Zampini       }
56090e6343abSStefano Zampini     }
5610727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
5611b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
561272b8c272SStefano Zampini   }
561372b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
5614727cdba6SStefano Zampini 
5615a717540cSStefano Zampini   /* flush dbg viewer */
5616b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
5617b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5618b8ffe317SStefano Zampini   }
5619a717540cSStefano Zampini 
5620e310c8b4SStefano Zampini   /* free workspace */
5621a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
56224641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
562308122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
56249162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
56259162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
562608122e43SStefano Zampini   } else {
56279162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
56289162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
56299162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
563008122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
563108122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
56329162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
56339162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
563408122e43SStefano Zampini   }
5635674ae819SStefano Zampini   PetscFunctionReturn(0);
5636674ae819SStefano Zampini }
5637674ae819SStefano Zampini 
5638674ae819SStefano Zampini #undef __FUNCT__
5639674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
5640674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
5641674ae819SStefano Zampini {
564271582508SStefano Zampini   ISLocalToGlobalMapping map;
5643674ae819SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5644674ae819SStefano Zampini   Mat_IS                 *matis  = (Mat_IS*)pc->pmat->data;
564514f95afaSStefano Zampini   PetscInt               ierr,i,N;
5646674ae819SStefano Zampini 
5647674ae819SStefano Zampini   PetscFunctionBegin;
5648c8272957SStefano Zampini   if (pcbddc->graphanalyzed && !pcbddc->recompute_topography) PetscFunctionReturn(0);
56498e61c736SStefano Zampini   /* Reset previously computed graph */
56508e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
5651674ae819SStefano Zampini   /* Init local Graph struct */
56527fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
565371582508SStefano Zampini   ierr = MatGetLocalToGlobalMapping(pc->pmat,&map,NULL);CHKERRQ(ierr);
5654be12c134Sstefano_zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount);CHKERRQ(ierr);
5655674ae819SStefano Zampini 
5656575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
56579a962809SStefano 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);
56589577ea80SStefano Zampini 
5659674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
5660d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
56614d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
56624d379d7bSStefano Zampini     PetscInt  nvtxs;
5663e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
5664674ae819SStefano Zampini 
56652fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
56662fffb893SStefano Zampini     if (flg_row) {
56674d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
5668b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
56692fffb893SStefano Zampini     }
56702fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5671674ae819SStefano Zampini   }
56729b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
56739b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5674674ae819SStefano Zampini   }
5675674ae819SStefano Zampini 
5676674ae819SStefano Zampini   /* Setup of Graph */
56774b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
567814f95afaSStefano 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);
5679674ae819SStefano Zampini 
56804f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
56814f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
56824f1b2e48SStefano Zampini     PetscInt *local_subs;
56834f1b2e48SStefano Zampini 
56844f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
56854f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
56864f1b2e48SStefano Zampini       const PetscInt *idxs;
56874f1b2e48SStefano Zampini       PetscInt       nl,j;
56884f1b2e48SStefano Zampini 
56894f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
56904f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
569171582508SStefano Zampini       for (j=0;j<nl;j++) local_subs[idxs[j]] = i;
56924f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
56934f1b2e48SStefano Zampini     }
56944f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
56954f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
56964f1b2e48SStefano Zampini   }
56974f1b2e48SStefano Zampini 
5698674ae819SStefano Zampini   /* Graph's connected components analysis */
5699674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
570071582508SStefano Zampini 
570171582508SStefano Zampini   /* set flag indicating analysis has been done */
570271582508SStefano Zampini   pcbddc->graphanalyzed = PETSC_TRUE;
5703674ae819SStefano Zampini   PetscFunctionReturn(0);
5704674ae819SStefano Zampini }
5705674ae819SStefano Zampini 
57069a7d3425SStefano Zampini #undef __FUNCT__
57079a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
57089a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
57099a7d3425SStefano Zampini {
57109a7d3425SStefano Zampini   PetscInt       i,j;
57119a7d3425SStefano Zampini   PetscScalar    *alphas;
57129a7d3425SStefano Zampini   PetscErrorCode ierr;
57139a7d3425SStefano Zampini 
57149a7d3425SStefano Zampini   PetscFunctionBegin;
5715785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
57169a7d3425SStefano Zampini   for (i=0;i<n;i++) {
57179a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
5718669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
5719669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
5720669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
57219a7d3425SStefano Zampini   }
57229a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
57239a7d3425SStefano Zampini   PetscFunctionReturn(0);
57249a7d3425SStefano Zampini }
57259a7d3425SStefano Zampini 
5726e7931f94SStefano Zampini #undef __FUNCT__
572770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
572857de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5729e7931f94SStefano Zampini {
573057de7509SStefano Zampini   Mat            A;
5731e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5732e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
573352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
573452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
573527b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
573657de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
573727b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
573827b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
573927b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
574027b6a85dSStefano Zampini   MPI_Comm       subcomm;
574152e5ac9dSStefano Zampini   PetscErrorCode ierr;
5742a57a6d2fSStefano Zampini 
5743e7931f94SStefano Zampini   PetscFunctionBegin;
574457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
574557de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
574657de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
574757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
574857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
574957de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
575057de7509SStefano Zampini 
575157de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
575257de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
575357de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
575457de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
575557de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
575657de7509SStefano Zampini   im_active = !!(n);
575757de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
575857de7509SStefano Zampini   void_procs = size - active_procs;
575957de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
576057de7509SStefano Zampini   if (void_procs) {
576157de7509SStefano Zampini     PetscInt ncand;
576257de7509SStefano Zampini 
576357de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
576457de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
576557de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
576657de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
576757de7509SStefano Zampini       if (!procs_candidates[i]) {
576857de7509SStefano Zampini         procs_candidates[ncand++] = i;
576957de7509SStefano Zampini       }
577057de7509SStefano Zampini     }
577157de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
577257de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
577357de7509SStefano Zampini   }
577457de7509SStefano Zampini 
577514f0bfb9SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix
577614f0bfb9SStefano Zampini      number of subdomains requested 1 -> send to master or first candidate in voids  */
577714f0bfb9SStefano Zampini   if (active_procs < *n_subdomains || *n_subdomains == 1) {
577814f0bfb9SStefano Zampini     PetscInt issize,isidx,dest;
577914f0bfb9SStefano Zampini     if (*n_subdomains == 1) dest = 0;
578014f0bfb9SStefano Zampini     else dest = rank;
578157de7509SStefano Zampini     if (im_active) {
578257de7509SStefano Zampini       issize = 1;
578357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
578414f0bfb9SStefano Zampini         isidx = procs_candidates[dest];
578557de7509SStefano Zampini       } else {
578614f0bfb9SStefano Zampini         isidx = dest;
578757de7509SStefano Zampini       }
578857de7509SStefano Zampini     } else {
578957de7509SStefano Zampini       issize = 0;
579057de7509SStefano Zampini       isidx = -1;
579157de7509SStefano Zampini     }
579257de7509SStefano Zampini     *n_subdomains = active_procs;
579357de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
5794daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
579557de7509SStefano Zampini     PetscFunctionReturn(0);
579657de7509SStefano Zampini   }
5797c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
5798c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
579927b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
5800e7931f94SStefano Zampini 
5801e7931f94SStefano Zampini   /* Get info on mapping */
58023bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
58033bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5804e7931f94SStefano Zampini 
5805e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
5806785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
5807e7931f94SStefano Zampini   xadj[0] = 0;
5808e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
5809785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
5810785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
581127b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
581227b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
581327b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
581427b6a85dSStefano Zampini       count[shared[i][j]] += 1;
5815e7931f94SStefano Zampini 
581627b6a85dSStefano Zampini   xadj_count = 0;
58172b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
581827b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
581927b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
5820d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
5821d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
5822d023bfaeSStefano Zampini         xadj_count++;
582327b6a85dSStefano Zampini         break;
582427b6a85dSStefano Zampini       }
5825e7931f94SStefano Zampini     }
5826e7931f94SStefano Zampini   }
5827d023bfaeSStefano Zampini   xadj[1] = xadj_count;
582827b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
58293bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5830e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
5831e7931f94SStefano Zampini 
58323837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
5833e7931f94SStefano Zampini 
583427b6a85dSStefano Zampini   /* Restrict work on active processes only */
583527b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
583627b6a85dSStefano Zampini   if (void_procs) {
583727b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
583827b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
583927b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
584027b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
584127b6a85dSStefano Zampini   } else {
584227b6a85dSStefano Zampini     psubcomm = NULL;
584327b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
584427b6a85dSStefano Zampini   }
584527b6a85dSStefano Zampini 
584627b6a85dSStefano Zampini   v_wgt = NULL;
584727b6a85dSStefano Zampini   if (!color) {
5848e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5849e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5850e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5851c8587f34SStefano Zampini   } else {
585252e5ac9dSStefano Zampini     Mat             subdomain_adj;
585352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
585452e5ac9dSStefano Zampini     MatPartitioning partitioner;
585527b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
585652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
585757de7509SStefano Zampini     PetscMPIInt     size;
5858b0c7d250SStefano Zampini     PetscBool       aggregate;
5859b0c7d250SStefano Zampini 
586027b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
586127b6a85dSStefano Zampini     if (void_procs) {
586227b6a85dSStefano Zampini       PetscInt prank = rank;
5863785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
586427b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5865e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5866e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5867c8587f34SStefano Zampini       }
5868e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
586927b6a85dSStefano Zampini     } else {
587027b6a85dSStefano Zampini       oldranks = NULL;
587127b6a85dSStefano Zampini     }
5872b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
587327b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5874b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5875b0c7d250SStefano Zampini       PetscMPIInt nrank;
5876b0c7d250SStefano Zampini       PetscScalar *vals;
5877b0c7d250SStefano Zampini 
587827b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5879b0c7d250SStefano Zampini       lrows = 0;
5880b0c7d250SStefano Zampini       if (nrank<redprocs) {
5881b0c7d250SStefano Zampini         lrows = size/redprocs;
5882b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5883b0c7d250SStefano Zampini       }
588427b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5885b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5886b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5887b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5888b0c7d250SStefano Zampini       row = nrank;
5889b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5890b0c7d250SStefano Zampini       cols = adjncy;
5891b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5892b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5893b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5894b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5895b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
589652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
589752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
589852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5899b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
590027b6a85dSStefano Zampini       if (use_vwgt) {
590127b6a85dSStefano Zampini         Vec               v;
590227b6a85dSStefano Zampini         const PetscScalar *array;
590327b6a85dSStefano Zampini         PetscInt          nl;
590427b6a85dSStefano Zampini 
590527b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
590627b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
590727b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
590827b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
590927b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
591027b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
591127b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
591222db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
591327b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
591427b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
591527b6a85dSStefano Zampini       }
5916b0c7d250SStefano Zampini     } else {
591727b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
591827b6a85dSStefano Zampini       if (use_vwgt) {
591927b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
592027b6a85dSStefano Zampini         v_wgt[0] = local_size;
592127b6a85dSStefano Zampini       }
5922b0c7d250SStefano Zampini     }
592322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5924e7931f94SStefano Zampini 
5925e7931f94SStefano Zampini     /* Partition */
592627b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5927e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
592827b6a85dSStefano Zampini     if (v_wgt) {
5929e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5930c8587f34SStefano Zampini     }
593157de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
593257de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5933e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5934e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
593522b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5936e7931f94SStefano Zampini 
593752e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
59386583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
593952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
594052e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
594157de7509SStefano Zampini     if (!aggregate) {
594257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
594327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
594427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
594527b6a85dSStefano Zampini #endif
594657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
594727b6a85dSStefano Zampini       } else if (oldranks) {
5948b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
594927b6a85dSStefano Zampini       } else {
595027b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
595157de7509SStefano Zampini       }
595228143c3dSStefano Zampini     } else {
5953b0c7d250SStefano Zampini       PetscInt    idxs[1];
5954b0c7d250SStefano Zampini       PetscMPIInt tag;
5955b0c7d250SStefano Zampini       MPI_Request *reqs;
5956b0c7d250SStefano Zampini 
5957b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5958b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5959b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
596027b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
596128143c3dSStefano Zampini       }
596227b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5963b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5964b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
596557de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
596627b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
596727b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
596827b6a85dSStefano Zampini #endif
596957de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
597027b6a85dSStefano Zampini       } else if (oldranks) {
5971b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
597227b6a85dSStefano Zampini       } else {
597327b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5974e7931f94SStefano Zampini       }
597557de7509SStefano Zampini     }
597652e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5977e7931f94SStefano Zampini     /* clean up */
5978e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
597952e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5980e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5981e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5982e7931f94SStefano Zampini   }
598327b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
598457de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5985e7931f94SStefano Zampini 
5986e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5987e7931f94SStefano Zampini   i = 1;
598827b6a85dSStefano Zampini   if (!color) i=0;
598957de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5990e7931f94SStefano Zampini   PetscFunctionReturn(0);
5991e7931f94SStefano Zampini }
5992e7931f94SStefano Zampini 
5993e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5994e7931f94SStefano Zampini 
5995e7931f94SStefano Zampini #undef __FUNCT__
5996e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
59971ae86dd6SStefano 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[])
5998e7931f94SStefano Zampini {
599970cf5478SStefano Zampini   Mat                    local_mat;
6000e7931f94SStefano Zampini   IS                     is_sends_internal;
60019d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
60021ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
60039d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
6004e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
6005e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
6006e7931f94SStefano Zampini   const PetscInt*        is_indices;
6007e7931f94SStefano Zampini   MatType                new_local_type;
6008e7931f94SStefano Zampini   /* buffers */
6009e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
601028143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
60119d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
6012e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
60131ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
6014e7931f94SStefano Zampini   /* MPI */
601528143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
601628143c3dSStefano Zampini   PetscSubcomm           subcomm;
6017e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
601828143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
601928143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
60201ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
60211ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
60221ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
6023e7931f94SStefano Zampini   PetscErrorCode         ierr;
6024e7931f94SStefano Zampini 
6025e7931f94SStefano Zampini   PetscFunctionBegin;
602657de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
6027e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
602828143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
602957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
603057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
603157de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
603257de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
603357de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
60341ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
60351ae86dd6SStefano Zampini   if (nvecs) {
60361ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
60371ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
60381ae86dd6SStefano Zampini   }
603957de7509SStefano Zampini   /* further checks */
6040e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6041e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
6042e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
6043e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
6044e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
604557de7509SStefano Zampini   if (reuse && *mat_n) {
604670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
604757de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
604870cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
604928143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
605070cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
605170cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
605270cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
605370cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
605470cf5478SStefano Zampini   }
6055e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
6056e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
605757de7509SStefano Zampini 
6058e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
6059e7931f94SStefano Zampini   if (!is_sends) {
606028143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
606157de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
6062c8587f34SStefano Zampini   } else {
6063e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
6064e7931f94SStefano Zampini     is_sends_internal = is_sends;
6065c8587f34SStefano Zampini   }
6066e7931f94SStefano Zampini 
6067e7931f94SStefano Zampini   /* get comm */
6068a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
6069e7931f94SStefano Zampini 
6070e7931f94SStefano Zampini   /* compute number of sends */
6071e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
6072e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
6073e7931f94SStefano Zampini 
6074e7931f94SStefano Zampini   /* compute number of receives */
6075e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
6076785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
6077e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
6078e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6079e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
6080e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
6081e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
6082e7931f94SStefano Zampini 
608328143c3dSStefano Zampini   /* restrict comm if requested */
608428143c3dSStefano Zampini   subcomm = 0;
608528143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
608628143c3dSStefano Zampini   if (restrict_comm) {
6087779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
6088779c1cceSStefano Zampini 
608928143c3dSStefano Zampini     color = 0;
609053a05cb3SStefano Zampini     if (restrict_full) {
609153a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
609253a05cb3SStefano Zampini     } else {
609353a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
609453a05cb3SStefano Zampini     }
6095b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
609628143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
609728143c3dSStefano Zampini     /* check if reuse has been requested */
609857de7509SStefano Zampini     if (reuse) {
609928143c3dSStefano Zampini       if (*mat_n) {
610028143c3dSStefano Zampini         PetscMPIInt subcommsize2;
610128143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
610228143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
610328143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
610428143c3dSStefano Zampini       } else {
610528143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
610628143c3dSStefano Zampini       }
610728143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
6108779c1cceSStefano Zampini       PetscMPIInt rank;
6109779c1cceSStefano Zampini 
6110779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
611128143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
611228143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
611328143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
6114306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
611528143c3dSStefano Zampini     }
611628143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
611728143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
611828143c3dSStefano Zampini   } else {
611928143c3dSStefano Zampini     comm_n = comm;
612028143c3dSStefano Zampini   }
612128143c3dSStefano Zampini 
6122e7931f94SStefano Zampini   /* prepare send/receive buffers */
6123785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
6124e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
6125785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
6126e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
612728143c3dSStefano Zampini   if (nis) {
6128854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
612928143c3dSStefano Zampini   }
6130e7931f94SStefano Zampini 
613128143c3dSStefano Zampini   /* Get data from local matrices */
61326c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
6133e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
6134e7931f94SStefano Zampini     /*
6135e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
6136e7931f94SStefano Zampini        send_buffer_idxs should contain:
6137e7931f94SStefano Zampini        - MatType_PRIVATE type
6138e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
6139e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
6140e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
6141e7931f94SStefano Zampini     */
61426c4ed002SBarry Smith   else {
6143e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
61443bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
6145854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
6146e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
6147e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
61483bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6149e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
61503bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
6151e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
6152e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
6153e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
6154e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
6155c8587f34SStefano Zampini     }
6156c8587f34SStefano Zampini   }
6157e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
615828143c3dSStefano Zampini   /* additional is (if any) */
615928143c3dSStefano Zampini   if (nis) {
616028143c3dSStefano Zampini     PetscMPIInt psum;
616128143c3dSStefano Zampini     PetscInt j;
616228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
616328143c3dSStefano Zampini       PetscInt plen;
616428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
616528143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
616628143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
616728143c3dSStefano Zampini     }
6168854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
616928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
617028143c3dSStefano Zampini       PetscInt plen;
617128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
617228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
617328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
617428143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
617528143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
617628143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
617728143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
617828143c3dSStefano Zampini     }
617928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
618028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
618128143c3dSStefano Zampini     }
618228143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
618328143c3dSStefano Zampini   }
618428143c3dSStefano Zampini 
6185e7931f94SStefano Zampini   buf_size_idxs = 0;
6186e7931f94SStefano Zampini   buf_size_vals = 0;
618728143c3dSStefano Zampini   buf_size_idxs_is = 0;
61881ae86dd6SStefano Zampini   buf_size_vecs = 0;
6189e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6190e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
6191e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
619228143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
61931ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
6194e7931f94SStefano Zampini   }
6195785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
6196785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
619795ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
61981ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
6199e7931f94SStefano Zampini 
6200e7931f94SStefano Zampini   /* get new tags for clean communications */
6201e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
6202e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
620328143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
62041ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
6205e7931f94SStefano Zampini 
6206e7931f94SStefano Zampini   /* allocate for requests */
6207785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
6208785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
620995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
62101ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
6211785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
6212785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
621395ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
62141ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
6215e7931f94SStefano Zampini 
6216e7931f94SStefano Zampini   /* communications */
6217e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
6218e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
621928143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
62201ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
6221e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6222e7931f94SStefano Zampini     source_dest = onodes[i];
6223e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
6224e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
6225e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6226e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
622728143c3dSStefano Zampini     if (nis) {
622857de7509SStefano Zampini       source_dest = onodes_is[i];
622928143c3dSStefano 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);
623028143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
623128143c3dSStefano Zampini     }
62321ae86dd6SStefano Zampini     if (nvecs) {
62331ae86dd6SStefano Zampini       source_dest = onodes[i];
62341ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
62351ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
62361ae86dd6SStefano Zampini     }
6237e7931f94SStefano Zampini   }
6238e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
6239e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
6240e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
6241e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
624228143c3dSStefano Zampini     if (nis) {
624328143c3dSStefano 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);
624428143c3dSStefano Zampini     }
62451ae86dd6SStefano Zampini     if (nvecs) {
62461ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
62471ae86dd6SStefano 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);
62481ae86dd6SStefano Zampini     }
6249e7931f94SStefano Zampini   }
6250e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
6251e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
6252e7931f94SStefano Zampini 
6253e7931f94SStefano Zampini   /* assemble new l2g map */
6254e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6255e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
62569d30be91SStefano Zampini   new_local_rows = 0;
6257e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
62589d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6259e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6260e7931f94SStefano Zampini   }
62619d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
6262e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
62639d30be91SStefano Zampini   new_local_rows = 0;
6264e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
62659d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
62669d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
6267e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6268e7931f94SStefano Zampini   }
62699d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
62709d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
6271e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
6272e7931f94SStefano Zampini 
6273e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
6274e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
6275e7931f94SStefano 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) */
6276e7931f94SStefano Zampini   if (n_recvs) {
627728143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
6278e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
6279e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
6280e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
6281e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
6282e7931f94SStefano Zampini         break;
6283e7931f94SStefano Zampini       }
6284e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
6285e7931f94SStefano Zampini     }
6286e7931f94SStefano Zampini     switch (new_local_type_private) {
628728143c3dSStefano Zampini       case MATDENSE_PRIVATE:
628828143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
6289e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
6290e7931f94SStefano Zampini           bs = 1;
629128143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
629228143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
629328143c3dSStefano Zampini           bs = 1;
629428143c3dSStefano Zampini         }
6295e7931f94SStefano Zampini         break;
6296e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
6297e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
6298e7931f94SStefano Zampini         bs = 1;
6299e7931f94SStefano Zampini         break;
6300e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
6301e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
6302e7931f94SStefano Zampini         break;
6303e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
6304e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
6305e7931f94SStefano Zampini         break;
6306e7931f94SStefano Zampini       default:
63079d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
6308e7931f94SStefano Zampini         break;
6309e7931f94SStefano Zampini     }
631028143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
631128143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
631228143c3dSStefano Zampini     bs = 1;
6313e7931f94SStefano Zampini   }
6314e7931f94SStefano Zampini 
631570cf5478SStefano Zampini   /* create MATIS object if needed */
631657de7509SStefano Zampini   if (!reuse) {
6317e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
6318e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
631970cf5478SStefano Zampini   } else {
632070cf5478SStefano Zampini     /* it also destroys the local matrices */
632157de7509SStefano Zampini     if (*mat_n) {
632270cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
632357de7509SStefano Zampini     } else { /* this is a fake object */
632457de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
632557de7509SStefano Zampini     }
632670cf5478SStefano Zampini   }
632770cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
6328e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
63299d30be91SStefano Zampini 
63309d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
63319d30be91SStefano Zampini 
63329d30be91SStefano Zampini   /* Global to local map of received indices */
63339d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
63349d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
63359d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
63369d30be91SStefano Zampini 
63379d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
63389d30be91SStefano Zampini   buf_size_idxs = 0;
63399d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
63409d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
63419d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
63429d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
63439d30be91SStefano Zampini   }
63449d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
63459d30be91SStefano Zampini 
63469d30be91SStefano Zampini   /* set preallocation */
63479d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
63489d30be91SStefano Zampini   if (!newisdense) {
63499d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
63509d30be91SStefano Zampini 
63519d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
63529d30be91SStefano Zampini     if (n_recvs) {
63539d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
63549d30be91SStefano Zampini     }
63559d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
63569d30be91SStefano Zampini       PetscInt j;
63579d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
63589d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
63599d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
63609d30be91SStefano Zampini         }
63619d30be91SStefano Zampini       } else {
63629d30be91SStefano Zampini         /* TODO */
63639d30be91SStefano Zampini       }
63649d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
63659d30be91SStefano Zampini     }
63669d30be91SStefano Zampini     if (new_local_nnz) {
63679d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
63689d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
63699d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
63709d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
63719d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
63729d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
63739d30be91SStefano Zampini     } else {
63749d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
63759d30be91SStefano Zampini     }
63769d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
63779d30be91SStefano Zampini   } else {
63789d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
63799d30be91SStefano Zampini   }
6380e7931f94SStefano Zampini 
6381e7931f94SStefano Zampini   /* set values */
6382e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
63839d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
6384e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
6385e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
6386e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
63879d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
6388e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6389e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
6390e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
639128143c3dSStefano Zampini     } else {
639228143c3dSStefano Zampini       /* TODO */
6393e7931f94SStefano Zampini     }
6394e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
6395e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
6396e7931f94SStefano Zampini   }
6397e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6398e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
639970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
640070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64019d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
6402e7931f94SStefano Zampini 
6403dfd14d43SStefano Zampini #if 0
640428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
6405e7931f94SStefano Zampini     Vec       lvec,rvec;
6406e7931f94SStefano Zampini     PetscReal infty_error;
6407e7931f94SStefano Zampini 
64082a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
6409e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
6410e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
6411e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
641270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
6413e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
6414e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
6415e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
6416e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
6417e7931f94SStefano Zampini   }
641828143c3dSStefano Zampini #endif
6419e7931f94SStefano Zampini 
642028143c3dSStefano Zampini   /* assemble new additional is (if any) */
642128143c3dSStefano Zampini   if (nis) {
642228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
642328143c3dSStefano Zampini 
642428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6425854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
642628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
642728143c3dSStefano Zampini     psum = 0;
642828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
642928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
643028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
643128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
643228143c3dSStefano Zampini         psum += plen;
643328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
643428143c3dSStefano Zampini       }
643528143c3dSStefano Zampini     }
6436854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
6437854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
643828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
643928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
644028143c3dSStefano Zampini     }
644128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
644228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
644328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
644428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
644528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
644628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
644728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
644828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
644928143c3dSStefano Zampini       }
645028143c3dSStefano Zampini     }
645128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
645228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
645328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
645428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
645528143c3dSStefano Zampini     }
645628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
645728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
645828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
645928143c3dSStefano Zampini   }
6460e7931f94SStefano Zampini   /* free workspace */
646128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
6462e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6463e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
6464e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
6465e7931f94SStefano Zampini   if (isdense) {
6466e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
6467e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
6468e7931f94SStefano Zampini   } else {
6469e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
6470e7931f94SStefano Zampini   }
647128143c3dSStefano Zampini   if (nis) {
647228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
647328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
647428143c3dSStefano Zampini   }
64751ae86dd6SStefano Zampini 
64761ae86dd6SStefano Zampini   if (nvecs) {
64771ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
64781ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
64791ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64801ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
64811ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
64821ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
64831ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
64841ae86dd6SStefano Zampini     /* set values */
64851ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
64861ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
64871ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64881ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
64891ae86dd6SStefano Zampini       PetscInt j;
64901ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
64911ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
64921ae86dd6SStefano Zampini       }
64931ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
64941ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
64951ae86dd6SStefano Zampini     }
64961ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
64971ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
64981ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
64991ae86dd6SStefano Zampini   }
65001ae86dd6SStefano Zampini 
65011ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
65021ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
6503e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
6504e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
65051ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
650628143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
6507e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
6508e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
65091ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
651028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
6511e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
6512e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
6513e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
6514e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
6515e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
651628143c3dSStefano Zampini   if (nis) {
651728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
651828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
651928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
652028143c3dSStefano Zampini   }
652128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
652228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
652328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
652428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
652528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
652628143c3dSStefano Zampini     }
65271ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
65281ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
65291ae86dd6SStefano Zampini     }
653053a05cb3SStefano Zampini     *mat_n = NULL;
653128143c3dSStefano Zampini   }
6532e7931f94SStefano Zampini   PetscFunctionReturn(0);
6533e7931f94SStefano Zampini }
6534a57a6d2fSStefano Zampini 
653512edc857SStefano Zampini /* temporary hack into ksp private data structure */
6536af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
653712edc857SStefano Zampini 
6538c8587f34SStefano Zampini #undef __FUNCT__
6539c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
6540c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
6541c8587f34SStefano Zampini {
6542c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
6543c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
654420a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
65451ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
65469881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
654720a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
65486e683305SStefano Zampini   IS                     coarse_is,*isarray;
65496e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
655030368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
6551f9eb5b7dSStefano Zampini   PC                     pc_temp;
6552c8587f34SStefano Zampini   PCType                 coarse_pc_type;
6553c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
6554f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
65554f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
65566e683305SStefano Zampini   Mat                    t_coarse_mat_is;
655757de7509SStefano Zampini   PetscInt               ncoarse;
655868457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
655922bc73bbSStefano Zampini   PetscScalar            *array;
656057de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
656157de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
65629881197aSStefano Zampini   PetscErrorCode         ierr;
6563fdc09c96SStefano Zampini 
6564c8587f34SStefano Zampini   PetscFunctionBegin;
6565c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
656668457ee5SStefano 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 */
6567fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
65685a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
6569fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
6570f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
6571f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
6572f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
6573fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
657451bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
657551bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
6576dc4bcba2SStefano Zampini         PC        pc;
6577dc4bcba2SStefano Zampini         PetscBool isbddc;
6578dc4bcba2SStefano Zampini 
6579dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
6580dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
6581dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
6582dc4bcba2SStefano Zampini         if (isbddc) {
658363c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
658463c961adSStefano Zampini         } else {
6585727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
658663c961adSStefano Zampini         }
6587fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
6588fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
6589fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
6590f4ddd8eeSStefano Zampini       }
6591fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
6592fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
6593f4ddd8eeSStefano Zampini     }
659470cf5478SStefano Zampini     /* reset any subassembling information */
659557de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
659670cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
659757de7509SStefano Zampini     }
65986e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
6599fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
6600f4ddd8eeSStefano Zampini   }
660157de7509SStefano Zampini   /* assemble coarse matrix */
660257de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
660357de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
660457de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
660557de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
660618a45a71SStefano Zampini   } else {
660757de7509SStefano Zampini     coarse_mat = NULL;
660857de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
66096e683305SStefano Zampini   }
6610e7931f94SStefano Zampini 
6611abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
6612abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
6613abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
6614abbbba34SStefano Zampini 
6615abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
661622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
661722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
661822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
661922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
6620e176bc59SStefano 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);
66216e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
66226e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66236e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6624abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
6625abbbba34SStefano Zampini 
662657de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
662757de7509SStefano Zampini   im_active = !!(pcis->n);
662857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
662957de7509SStefano Zampini 
663014f0bfb9SStefano Zampini   /* determine number of processes partecipating to coarse solver and compute subassembling pattern */
663157de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
663257de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
663357de7509SStefano Zampini   coarse_mat_is = NULL;
663457de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
663557de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
663657de7509SStefano Zampini   full_restr = PETSC_TRUE;
66371ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
663857de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
663957de7509SStefano Zampini   if (multilevel_requested) {
664057de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
664157de7509SStefano Zampini     restr = PETSC_FALSE;
664257de7509SStefano Zampini     full_restr = PETSC_FALSE;
664357de7509SStefano Zampini   } else {
664457de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
664557de7509SStefano Zampini     restr = PETSC_TRUE;
664657de7509SStefano Zampini     full_restr = PETSC_TRUE;
664757de7509SStefano Zampini   }
66484b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
664957de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
665057de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
6651a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
665257de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
6653a198735bSStefano Zampini     } else {
6654a198735bSStefano Zampini       PetscMPIInt size,rank;
6655a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6656a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
6657a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
6658a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
6659a198735bSStefano Zampini     }
666057de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
666157de7509SStefano Zampini     PetscInt    psum;
666257de7509SStefano Zampini     PetscMPIInt size;
666357de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
666457de7509SStefano Zampini     else psum = 0;
666557de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
666657de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
666757de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
666857de7509SStefano Zampini   }
666957de7509SStefano Zampini   /* determine if we can go multilevel */
667057de7509SStefano Zampini   if (multilevel_requested) {
667157de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
667257de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
667357de7509SStefano Zampini   }
667457de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
667557de7509SStefano Zampini 
6676e4d548c7SStefano Zampini   /* dump subassembling pattern */
6677e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
6678e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
6679e4d548c7SStefano Zampini   }
6680e4d548c7SStefano Zampini 
66816e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
668227b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
66836e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
66846e683305SStefano Zampini     const PetscInt         *idxs;
66856e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
66866e683305SStefano Zampini 
66876e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
66880be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
66896e683305SStefano Zampini     /* allocate space for temporary storage */
6690854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
6691854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
66926e683305SStefano Zampini     /* allocate for IS array */
66936e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
66946e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
669527b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
669630368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
6697854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
66986e683305SStefano Zampini     /* dofs splitting */
66996e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
67006e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
67016e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
67026e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
67036e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
67046e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
67056e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
670630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
67076e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
67086e683305SStefano Zampini     }
67096e683305SStefano Zampini     /* neumann boundaries */
67106e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
67116e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
67126e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
67136e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
67146e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
67156e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
67166e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
671730368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
67186e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
67196e683305SStefano Zampini     }
67206e683305SStefano Zampini     /* free memory */
67216e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
67226e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
67236e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
67246e683305SStefano Zampini   } else {
67256e683305SStefano Zampini     nis = 0;
67266e683305SStefano Zampini     nisdofs = 0;
67276e683305SStefano Zampini     nisneu = 0;
672830368db7SStefano Zampini     nisvert = 0;
67296e683305SStefano Zampini     isarray = NULL;
67306e683305SStefano Zampini   }
67316e683305SStefano Zampini   /* destroy no longer needed map */
67326e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
67336e683305SStefano Zampini 
673457de7509SStefano Zampini   /* subassemble */
673557de7509SStefano Zampini   if (multilevel_allowed) {
67361ae86dd6SStefano Zampini     Vec       vp[1];
67371ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
673857de7509SStefano Zampini     PetscBool reuse,reuser;
67391ae86dd6SStefano Zampini 
674057de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
674157de7509SStefano Zampini     else reuse = PETSC_FALSE;
674257de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
67431ae86dd6SStefano Zampini     vp[0] = NULL;
67441ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
67451ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
67461ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
67471ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
67481ae86dd6SStefano Zampini       nvecs = 1;
67491ae86dd6SStefano Zampini 
67501ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6751a198735bSStefano Zampini         Mat      B,loc_divudotp;
67521ae86dd6SStefano Zampini         Vec      v,p;
67531ae86dd6SStefano Zampini         IS       dummy;
67541ae86dd6SStefano Zampini         PetscInt np;
67551ae86dd6SStefano Zampini 
6756a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6757a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
67581ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6759a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
67601ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
67611ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
67621ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
67631ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
67641ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
67651ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
67661ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
67671ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
67681ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
67691ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
67701ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
67711ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
677274e2c79eSStefano Zampini       }
67731ae86dd6SStefano Zampini     }
67741ae86dd6SStefano Zampini     if (reuser) {
67751ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
677674e2c79eSStefano Zampini     } else {
67771ae86dd6SStefano 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);
67781ae86dd6SStefano Zampini     }
67791ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
67801ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
67811ae86dd6SStefano Zampini       PetscInt    nl;
67821ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
67831ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
67841ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
67851ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
67861ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
67871ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
67881ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
67891ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
6790a198735bSStefano Zampini     } else {
6791a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
67921ae86dd6SStefano Zampini     }
67931ae86dd6SStefano Zampini   } else {
67941ae86dd6SStefano 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);
67956e683305SStefano Zampini   }
679657de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
679757de7509SStefano Zampini     PetscMPIInt size;
679857de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
679957de7509SStefano Zampini     if (!multilevel_allowed) {
680057de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
68016e683305SStefano Zampini     } else {
680257de7509SStefano Zampini       Mat A;
6803779c1cceSStefano Zampini 
680457de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
680557de7509SStefano Zampini       if (coarse_mat_is) {
680657de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
680757de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
680857de7509SStefano Zampini         coarse_mat = coarse_mat_is;
680957de7509SStefano Zampini       }
681057de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
681157de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
681257de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
6813779c1cceSStefano Zampini     }
6814779c1cceSStefano Zampini   }
681557de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
681657de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
68176e683305SStefano Zampini 
68186e683305SStefano Zampini   /* create local to global scatters for coarse problem */
681968457ee5SStefano Zampini   if (compute_vecs) {
68206e683305SStefano Zampini     PetscInt lrows;
68216e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
682257de7509SStefano Zampini     if (coarse_mat) {
682357de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
68246e683305SStefano Zampini     } else {
68256e683305SStefano Zampini       lrows = 0;
68266e683305SStefano Zampini     }
68276e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
68286e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
68296e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
68306e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
68316e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
68326e683305SStefano Zampini   }
68336e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
6834c8587f34SStefano Zampini 
6835f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
6836f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
6837f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
6838f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
6839f9eb5b7dSStefano Zampini   } else {
6840f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
6841f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
6842c8587f34SStefano Zampini   }
6843c8587f34SStefano Zampini 
68446e683305SStefano Zampini   /* print some info if requested */
68456e683305SStefano Zampini   if (pcbddc->dbg_flag) {
68466e683305SStefano Zampini     if (!multilevel_allowed) {
68476e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
68486e683305SStefano Zampini       if (multilevel_requested) {
68496e683305SStefano 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);
68506e683305SStefano Zampini       } else if (pcbddc->max_levels) {
68516e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
68526e683305SStefano Zampini       }
68536e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
68546e683305SStefano Zampini     }
68556e683305SStefano Zampini   }
68566e683305SStefano Zampini 
6857f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
685857de7509SStefano Zampini   if (coarse_mat) {
68596a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
68606e683305SStefano Zampini     if (pcbddc->dbg_flag) {
686157de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
68626e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
68636e683305SStefano Zampini     }
6864f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
6865312be037SStefano Zampini       char prefix[256],str_level[16];
6866e604994aSStefano Zampini       size_t len;
686757de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
6868422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
6869c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
6870f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
687157de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6872c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
68736e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
6874c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
6875c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6876e604994aSStefano Zampini       /* prefix */
6877e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
6878e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
6879e604994aSStefano Zampini       if (!pcbddc->current_level) {
6880e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
6881e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
6882c8587f34SStefano Zampini       } else {
6883e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
6884312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
6885312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
688634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
6887312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
6888e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
6889e604994aSStefano Zampini       }
6890e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
68913e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
68923e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
68933e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
68943e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
6895f9eb5b7dSStefano Zampini       /* allow user customization */
6896f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
68973e3c6dadSStefano Zampini     }
68983e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
689951bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
69003e3c6dadSStefano Zampini     if (nisdofs) {
69013e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
69023e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
69033e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
69043e3c6dadSStefano Zampini       }
69053e3c6dadSStefano Zampini     }
69063e3c6dadSStefano Zampini     if (nisneu) {
69073e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
69083e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
6909312be037SStefano Zampini     }
691030368db7SStefano Zampini     if (nisvert) {
691130368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
691230368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
691330368db7SStefano Zampini     }
6914f9eb5b7dSStefano Zampini 
6915f9eb5b7dSStefano Zampini     /* get some info after set from options */
6916f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
6917f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
69184f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
69196e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
6920f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6921f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
6922f9eb5b7dSStefano Zampini     }
692339f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
69244f3a063dSStefano Zampini     if (isredundant) {
69254f3a063dSStefano Zampini       KSP inner_ksp;
69264f3a063dSStefano Zampini       PC  inner_pc;
69274f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
69284f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
69294f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
69304f3a063dSStefano Zampini     }
6931f9eb5b7dSStefano Zampini 
693257de7509SStefano Zampini     /* parameters which miss an API */
693357de7509SStefano Zampini     if (isbddc) {
6934720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
6935720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
693657de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
693727b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
693827b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
6939a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
6940a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
6941a198735bSStefano Zampini         IS                     row,col;
6942a198735bSStefano Zampini         const PetscInt         *gidxs;
6943a198735bSStefano Zampini         PetscInt               n,st,M,N;
6944a198735bSStefano Zampini 
6945a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
6946a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
6947a198735bSStefano Zampini         st = st-n;
6948a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
6949a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
6950a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
6951a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6952a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
6953a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6954a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
6955a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
6956a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
6957a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
6958a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
6959a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
6960a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
6961a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
6962a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
6963a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
6964a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6965a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6966a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
6967a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
69688ae0ca82SStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL);CHKERRQ(ierr);
6969a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
6970720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
697159e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6972720d30f9SStefano Zampini       }
6973d4d8cf7bSStefano Zampini     }
69749881197aSStefano Zampini 
69753301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
69765a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
69773301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
69783301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
69793301b35fSStefano Zampini     }
69803301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
69813301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
69823301b35fSStefano Zampini     }
69833301b35fSStefano Zampini     if (pc->pmat->spd_set) {
69843301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
69853301b35fSStefano Zampini     }
698627b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
698727b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
698827b6a85dSStefano Zampini     }
69896e683305SStefano Zampini     /* set operators */
69905f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
69916e683305SStefano Zampini     if (pcbddc->dbg_flag) {
69926e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
69936e683305SStefano Zampini     }
69946e683305SStefano Zampini   }
69956e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6996b1ecc7b1SStefano Zampini #if 0
6997b9b85e73SStefano Zampini   {
6998b9b85e73SStefano Zampini     PetscViewer viewer;
6999b9b85e73SStefano Zampini     char filename[256];
7000b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
7001b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
70026a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
7003b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
7004f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
7005b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
7006b9b85e73SStefano Zampini   }
7007b9b85e73SStefano Zampini #endif
7008f9eb5b7dSStefano Zampini 
700998a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
701098a51de6SStefano Zampini     Vec crhs,csol;
701104708bb6SStefano Zampini 
7012f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
7013f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
7014f347579bSStefano Zampini     if (!csol) {
70152a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
7016f9eb5b7dSStefano Zampini     }
7017f347579bSStefano Zampini     if (!crhs) {
70182a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
7019f347579bSStefano Zampini     }
7020b0f5fe93SStefano Zampini   }
70211ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
7022b0f5fe93SStefano Zampini 
7023b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
7024b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
7025b0f5fe93SStefano Zampini 
7026b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
70274f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
70284f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
70294f1b2e48SStefano Zampini     }
7030b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
7031b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
7032b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7033b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7034b0f5fe93SStefano Zampini     if (coarse_mat) {
7035b0f5fe93SStefano Zampini       Vec         nullv;
7036b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
7037b0f5fe93SStefano Zampini       PetscInt    nl;
7038b0f5fe93SStefano Zampini 
7039b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
7040b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
7041b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7042b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
7043b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
7044b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
7045b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
7046b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
7047b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
7048b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
7049b0f5fe93SStefano Zampini     }
7050b0f5fe93SStefano Zampini   }
7051b0f5fe93SStefano Zampini 
7052b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
7053b0f5fe93SStefano Zampini     PetscBool ispreonly;
7054b0f5fe93SStefano Zampini 
7055b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
7056b0f5fe93SStefano Zampini       PetscBool isnull;
7057b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
7058bef83e63SStefano Zampini       if (isnull) {
7059b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
7060b0f5fe93SStefano Zampini       }
7061bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
7062b0f5fe93SStefano Zampini     }
7063b0f5fe93SStefano Zampini     /* setup coarse ksp */
7064b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
7065cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
7066cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
70676e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
7068c8587f34SStefano Zampini       KSP       check_ksp;
70692b510759SStefano Zampini       KSPType   check_ksp_type;
7070c8587f34SStefano Zampini       PC        check_pc;
70716e683305SStefano Zampini       Vec       check_vec,coarse_vec;
70726a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
70732b510759SStefano Zampini       PetscInt  its;
70746e683305SStefano Zampini       PetscBool compute_eigs;
70756e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
70766e683305SStefano Zampini       PetscInt  neigs;
70778e185a42SStefano Zampini       const char *prefix;
7078c8587f34SStefano Zampini 
70792b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
70806e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
7081422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
708223ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
7083f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
7084e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
7085e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
7086e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
70872b510759SStefano Zampini       if (ispreonly) {
70882b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
70896e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
70902b510759SStefano Zampini       } else {
7091cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
70926e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
7093c8587f34SStefano Zampini       }
7094c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
70956e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
70966e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
70976e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
7098a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
7099a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
7100a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
7101a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
7102c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
7103c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
7104c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
7105c8587f34SStefano Zampini       /* create random vec */
71062701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
7107c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
71086e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
7109c8587f34SStefano Zampini       /* solve coarse problem */
71106e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
7111cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
71126e683305SStefano Zampini       if (compute_eigs) {
7113854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
7114854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
71156e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
71161ae86dd6SStefano Zampini         if (neigs) {
71176e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
71186e683305SStefano Zampini           lambda_min = eigs_r[0];
71196e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
71202701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
71212701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
7122cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
7123cbcc2c2aSStefano Zampini             }
7124c8587f34SStefano Zampini           }
7125c8587f34SStefano Zampini         }
71261ae86dd6SStefano Zampini       }
7127cbcc2c2aSStefano Zampini 
7128c8587f34SStefano Zampini       /* check coarse problem residual error */
71296e683305SStefano Zampini       if (pcbddc->dbg_flag) {
71306e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
71316e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
71326e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
7133c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
71346e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
71356e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
7136779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
71376e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
71386e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
71396e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
71406e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
7141b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
7142b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
7143b0f5fe93SStefano Zampini         }
71446e683305SStefano Zampini         if (compute_eigs) {
71456e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
7146deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
7147c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
71486e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
71496e683305SStefano 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);
71506e683305SStefano Zampini           for (i=0;i<neigs;i++) {
71516e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
7152c8587f34SStefano Zampini           }
71536e683305SStefano Zampini         }
71546e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
71556e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
71566e683305SStefano Zampini       }
7157e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
71582701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
7159c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
71606e683305SStefano Zampini       if (compute_eigs) {
71616e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
71626e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
7163c8587f34SStefano Zampini       }
71646e683305SStefano Zampini     }
71656e683305SStefano Zampini   }
7166bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
7167cbcc2c2aSStefano Zampini   /* print additional info */
7168cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
71696e683305SStefano Zampini     /* waits until all processes reaches this point */
71706e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
7171cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
7172cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7173cbcc2c2aSStefano Zampini   }
7174cbcc2c2aSStefano Zampini 
71752b510759SStefano Zampini   /* free memory */
7176fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
7177c8587f34SStefano Zampini   PetscFunctionReturn(0);
7178c8587f34SStefano Zampini }
7179674ae819SStefano Zampini 
7180f34684f1SStefano Zampini #undef __FUNCT__
7181f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
7182f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
7183f34684f1SStefano Zampini {
7184f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7185f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
7186f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7187dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
7188dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
718973be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
7190dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
7191f34684f1SStefano Zampini   PetscErrorCode ierr;
7192f34684f1SStefano Zampini 
7193f34684f1SStefano Zampini   PetscFunctionBegin;
7194f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
71956c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
7196dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
71973bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
7198dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7199dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
72006583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
7201dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
7202dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
7203dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
72046c4ed002SBarry 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);
7205dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
7206dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7207dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
7208dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
7209dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
7210f34684f1SStefano Zampini 
7211f34684f1SStefano Zampini   /* check numbering */
7212f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
7213019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
7214dc456d91SStefano Zampini     PetscInt    i;
7215b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
7216f34684f1SStefano Zampini 
7217f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7218f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7219f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
72201575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7221019a44ceSStefano Zampini     /* counter */
7222019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7223019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
7224019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7225019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7226019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7227019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7228f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
7229f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
7230727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
7231f34684f1SStefano Zampini     }
7232f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7233f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7234f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7235e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7236e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7237e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7238e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7239f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7240019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7241f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7242019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
72432c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
724475c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
7245b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
72462c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
72472c66d082SStefano 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);
7248f34684f1SStefano Zampini       }
7249f34684f1SStefano Zampini     }
7250019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
7251b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
7252f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7253f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
7254f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
7255f34684f1SStefano Zampini     }
7256f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7257f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
7258e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7259e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7260f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
7261f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
7262b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
7263ca8b9ea9SStefano Zampini       PetscInt *gidxs;
7264ca8b9ea9SStefano Zampini 
7265ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
72663bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
7267f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
7268f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7269f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
7270f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
72714bc2dc4bSStefano 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);
7272f34684f1SStefano Zampini       }
7273f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7274ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
7275f34684f1SStefano Zampini     }
7276f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
72771575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7278302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
7279f34684f1SStefano Zampini   }
72808bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
7281f34684f1SStefano Zampini   /* get back data */
7282f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
7283f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
7284674ae819SStefano Zampini   PetscFunctionReturn(0);
7285674ae819SStefano Zampini }
7286674ae819SStefano Zampini 
7287e456f2a8SStefano Zampini #undef __FUNCT__
7288e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
7289a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
7290e456f2a8SStefano Zampini {
7291e456f2a8SStefano Zampini   IS             localis_t;
7292a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
7293e456f2a8SStefano Zampini   PetscScalar    *vals;
7294e456f2a8SStefano Zampini   PetscErrorCode ierr;
7295e456f2a8SStefano Zampini 
7296e456f2a8SStefano Zampini   PetscFunctionBegin;
7297a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
7298e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
7299854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
7300e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
7301e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7302a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
7303a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
73041035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
7305a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
73061035eff8SStefano Zampini   }
7307a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
7308e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
7309e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
7310a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
7311a7dc3881SStefano Zampini   /* now compute set in local ordering */
7312a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7313a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7314a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7315a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
7316a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7317ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7318e456f2a8SStefano Zampini       lsize++;
7319e456f2a8SStefano Zampini     }
7320e456f2a8SStefano Zampini   }
7321854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
7322a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
7323ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
7324e456f2a8SStefano Zampini       idxs[lsize++] = i;
7325e456f2a8SStefano Zampini     }
7326e456f2a8SStefano Zampini   }
7327a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
7328a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
7329e456f2a8SStefano Zampini   *localis = localis_t;
7330e456f2a8SStefano Zampini   PetscFunctionReturn(0);
7331e456f2a8SStefano Zampini }
7332906d46d4SStefano Zampini 
7333b96c3477SStefano Zampini #undef __FUNCT__
7334b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
733508122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
7336b96c3477SStefano Zampini {
7337a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7338b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7339b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
7340a64f4aa4SStefano Zampini   Mat                 S_j;
7341b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
7342b96c3477SStefano Zampini   PetscBool           free_used_adj;
7343b96c3477SStefano Zampini   PetscErrorCode      ierr;
7344b96c3477SStefano Zampini 
7345b96c3477SStefano Zampini   PetscFunctionBegin;
7346b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
7347b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
734808122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
7349b96c3477SStefano Zampini     used_xadj = NULL;
7350b96c3477SStefano Zampini     used_adjncy = NULL;
7351b96c3477SStefano Zampini   } else {
735208122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
735308122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
735408122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
735508122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
7356b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
7357b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
7358b96c3477SStefano Zampini     } else {
73592fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
7360b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
7361b96c3477SStefano Zampini       PetscInt       nvtxs;
7362b96c3477SStefano Zampini 
73632fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
73642fffb893SStefano Zampini       if (flg_row) {
7365b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
7366b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
7367b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
7368b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
73692fffb893SStefano Zampini       } else {
73702fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
73712fffb893SStefano Zampini         used_xadj = NULL;
73722fffb893SStefano Zampini         used_adjncy = NULL;
73732fffb893SStefano Zampini       }
73742fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
7375b96c3477SStefano Zampini     }
7376b96c3477SStefano Zampini   }
7377d5574798SStefano Zampini 
7378d5574798SStefano Zampini   /* setup sub_schurs data */
7379a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7380df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
7381df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
7382a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
738391af6908SStefano 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);
7384a64f4aa4SStefano Zampini   } else {
73856816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
73864d7f8f00SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;
7387a3df083aSStefano Zampini     PetscInt  benign_n;
738872b8c272SStefano Zampini     Mat       change = NULL;
73899d54b7f4SStefano Zampini     Vec       scaling = NULL;
739072b8c272SStefano Zampini     IS        change_primal = NULL;
7391a3df083aSStefano Zampini 
73925feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
73935feab87aSStefano Zampini       PetscInt n_vertices;
73945feab87aSStefano Zampini 
73955feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
73962034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
73975feab87aSStefano Zampini     }
739804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
739904708bb6SStefano Zampini     if (!isseqaij) {
740004708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
740104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
740204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
740304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
740404708bb6SStefano Zampini       } else {
7405511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
740604708bb6SStefano Zampini       }
740704708bb6SStefano Zampini     }
7408a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
7409a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
7410ca92afb2SStefano Zampini     } else {
7411a3df083aSStefano Zampini       benign_n = 0;
7412ca92afb2SStefano Zampini     }
7413b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
7414b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
7415b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
741672b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
741722db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
7418b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
741922db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
7420b7ab4a40SStefano Zampini     }
7421b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
7422b7ab4a40SStefano 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 */
7423b7ab4a40SStefano Zampini     if (need_change) {
742488c03ad3SStefano Zampini       PC_IS   *pcisf;
742588c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
742688c03ad3SStefano Zampini       PC      pcf;
742788c03ad3SStefano Zampini 
7428e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
742988c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
743088c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
743188c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
743288c03ad3SStefano Zampini       /* hacks */
743388c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
743472b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
743572b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
743672b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
743772b8c272SStefano Zampini       pcisf->n = pcis->n;
743872b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
743988c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
744088c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
744188c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
744288c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
744388c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
744488c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
744572b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
744688c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
744788c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
744872b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
744972b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
745072b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
745172b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
745272b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
745388c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
745472b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
745588c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
745688c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
745788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
745888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
745988c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
746088c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
746188c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
746288c03ad3SStefano Zampini     }
74639d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
746491af6908SStefano 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);
746572b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
746672b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
7467ca92afb2SStefano Zampini   }
7468d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7469b96c3477SStefano Zampini 
7470b96c3477SStefano Zampini   /* free adjacency */
7471b96c3477SStefano Zampini   if (free_used_adj) {
7472b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
7473b96c3477SStefano Zampini   }
7474b96c3477SStefano Zampini   PetscFunctionReturn(0);
7475b96c3477SStefano Zampini }
7476b96c3477SStefano Zampini 
7477b96c3477SStefano Zampini #undef __FUNCT__
7478b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
747908122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
7480b96c3477SStefano Zampini {
7481b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7482b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7483b96c3477SStefano Zampini   PCBDDCGraph         graph;
7484b96c3477SStefano Zampini   PetscErrorCode      ierr;
7485b96c3477SStefano Zampini 
7486b96c3477SStefano Zampini   PetscFunctionBegin;
7487b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
748808122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
74893301b35fSStefano Zampini     IS       verticesIS,verticescomm;
74903301b35fSStefano Zampini     PetscInt vsize,*idxs;
7491b96c3477SStefano Zampini 
7492b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
74933301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
74943301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
74953301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
74963301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
7497c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
7498b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
7499be12c134Sstefano_zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount);CHKERRQ(ierr);
7500441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
75013301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
7502b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
7503b96c3477SStefano Zampini   } else {
7504b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
7505b96c3477SStefano Zampini   }
7506e4d548c7SStefano Zampini   /* print some info */
7507e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
7508e4d548c7SStefano Zampini     IS       vertices;
7509e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
7510c8272957SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
7511e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7512e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
7513e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7514e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
7515e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
7516e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
7517e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
7518e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
7519e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
7520c8272957SStefano Zampini     ierr = PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
7521e4d548c7SStefano Zampini   }
7522b96c3477SStefano Zampini 
7523b96c3477SStefano Zampini   /* sub_schurs init */
7524b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
7525b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
7526b334f244SStefano Zampini   }
7527b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
7528a64f4aa4SStefano Zampini 
7529b96c3477SStefano Zampini   /* free graph struct */
753008122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
7531b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
7532b96c3477SStefano Zampini   }
7533b96c3477SStefano Zampini   PetscFunctionReturn(0);
7534b96c3477SStefano Zampini }
7535fa34dd3eSStefano Zampini 
7536fa34dd3eSStefano Zampini #undef __FUNCT__
7537fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
7538fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
7539fa34dd3eSStefano Zampini {
7540fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
7541fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
7542fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
7543fa34dd3eSStefano Zampini 
7544fa34dd3eSStefano Zampini   PetscFunctionBegin;
7545fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
7546fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
75474f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
7548fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
75494f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
755075c01103SStefano Zampini     PetscReal      norm;
7551fa34dd3eSStefano Zampini     PetscInt       i;
7552fa34dd3eSStefano Zampini 
7553fa34dd3eSStefano Zampini     /* B0 and B0_B */
7554fa34dd3eSStefano Zampini     if (zerodiag) {
7555fa34dd3eSStefano Zampini       IS       dummy;
7556fa34dd3eSStefano Zampini 
75574f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
75584f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
7559fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
7560fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
7561fa34dd3eSStefano Zampini     }
7562fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
7563fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
7564fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
7565fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7566fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7567fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7568fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7569fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
7570fa34dd3eSStefano Zampini     /* S_j */
7571fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
7572fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
7573fa34dd3eSStefano Zampini 
7574fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
7575fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
7576fa34dd3eSStefano Zampini     /* continuous in primal space */
7577fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
7578fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7579fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7580fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
75814f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
75824f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
7583fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7584fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7585fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7586fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7587fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7588fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7589fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
7590fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
7591fa34dd3eSStefano Zampini 
7592fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
7593fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
7594fa34dd3eSStefano Zampini     /* local with Schur */
7595fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
7596fa34dd3eSStefano Zampini     if (zerodiag) {
7597fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
75984f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
7599fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7600fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7601fa34dd3eSStefano Zampini     }
7602fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
7603fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7604fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7605fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7606fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7607fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
7608fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
7609fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7610fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
7611fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7612fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7613fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7614fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7615fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7616fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
7617fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
7618fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
7619fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
7620fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
7621fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
7622fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7623fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7624fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
7625fa34dd3eSStefano Zampini     if (zerodiag) {
7626fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
7627fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
76284f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
7629fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
7630fa34dd3eSStefano Zampini     }
7631fa34dd3eSStefano Zampini     /* BDDC */
7632fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
7633fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
7634fa34dd3eSStefano Zampini 
7635fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
7636fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
7637fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
7638fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
76394f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
76404f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
7641fa34dd3eSStefano Zampini     }
76424f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
7643fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
7644fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
7645fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
7646fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
7647fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
7648fa34dd3eSStefano Zampini   }
7649fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
7650fa34dd3eSStefano Zampini }
7651