xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 683d3df6f9c0b211a07d9c40891fbe6b48cc9b85)
1 #include <../src/mat/impls/aij/seq/aij.h>
2 #include <../src/ksp/pc/impls/bddc/bddc.h>
3 #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4 #include <petscblaslapack.h>
5 
6 static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
7 static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
8 
9 /* TODO: add reuse flag */
10 #undef __FUNCT__
11 #define __FUNCT__ "MatSeqAIJCompress"
12 PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
13 {
14   Mat            Bt;
15   PetscScalar    *a,*bdata;
16   const PetscInt *ii,*ij;
17   PetscInt       m,n,i,nnz,*bii,*bij;
18   PetscBool      flg_row;
19   PetscErrorCode ierr;
20 
21   PetscFunctionBegin;
22   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
23   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
24   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
25   nnz = n;
26   for (i=0;i<ii[n];i++) {
27     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
28   }
29   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
30   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
31   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
32   nnz = 0;
33   bii[0] = 0;
34   for (i=0;i<n;i++) {
35     PetscInt j;
36     for (j=ii[i];j<ii[i+1];j++) {
37       PetscScalar entry = a[j];
38       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
39         bij[nnz] = ij[j];
40         bdata[nnz] = entry;
41         nnz++;
42       }
43     }
44     bii[i+1] = nnz;
45   }
46   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
47   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
48   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
49   {
50     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
51     b->free_a = PETSC_TRUE;
52     b->free_ij = PETSC_TRUE;
53   }
54   *B = Bt;
55   PetscFunctionReturn(0);
56 }
57 
58 #undef __FUNCT__
59 #define __FUNCT__ "MatDetectDisconnectedComponents"
60 PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
61 {
62   Mat                    B;
63   IS                     is_dummy,*cc_n;
64   ISLocalToGlobalMapping l2gmap_dummy;
65   PCBDDCGraph            graph;
66   PetscInt               i,n;
67   PetscInt               *xadj,*adjncy;
68   PetscInt               *xadj_filtered,*adjncy_filtered;
69   PetscBool              flg_row,isseqaij;
70   PetscErrorCode         ierr;
71 
72   PetscFunctionBegin;
73   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
74   if (!isseqaij && filter) {
75     PetscBool isseqdense;
76 
77     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
78     if (!isseqdense) {
79       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
80     } else { /* TODO: rectangular case and LDA */
81       PetscScalar *array;
82       PetscReal   chop=1.e-6;
83 
84       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
85       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
86       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
87       for (i=0;i<n;i++) {
88         PetscInt j;
89         for (j=i+1;j<n;j++) {
90           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
91           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
92           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
93         }
94       }
95       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
96       ierr = MatConvert(B,MATSEQAIJ,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
97     }
98   } else {
99     B = A;
100   }
101   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
102 
103   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
104   if (filter) {
105     PetscScalar *data;
106     PetscInt    j,cum;
107 
108     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
109     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
110     cum = 0;
111     for (i=0;i<n;i++) {
112       PetscInt t;
113 
114       for (j=xadj[i];j<xadj[i+1];j++) {
115         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
116           continue;
117         }
118         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
119       }
120       t = xadj_filtered[i];
121       xadj_filtered[i] = cum;
122       cum += t;
123     }
124     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
125   } else {
126     xadj_filtered = NULL;
127     adjncy_filtered = NULL;
128   }
129 
130   /* compute local connected components using PCBDDCGraph */
131   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
132   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
133   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
134   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
135   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
136   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
137   if (xadj_filtered) {
138     graph->xadj = xadj_filtered;
139     graph->adjncy = adjncy_filtered;
140   } else {
141     graph->xadj = xadj;
142     graph->adjncy = adjncy;
143   }
144   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
145   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
146   /* partial clean up */
147   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
148   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
149   if (A != B) {
150     ierr = MatDestroy(&B);CHKERRQ(ierr);
151   }
152 
153   /* get back data */
154   if (ncc) *ncc = graph->ncc;
155   if (cc) {
156     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
157     for (i=0;i<graph->ncc;i++) {
158       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);
159     }
160     *cc = cc_n;
161   }
162   /* clean up graph */
163   graph->xadj = 0;
164   graph->adjncy = 0;
165   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
166   PetscFunctionReturn(0);
167 }
168 
169 #undef __FUNCT__
170 #define __FUNCT__ "PCBDDCBenignCheck"
171 PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
172 {
173   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
174   PC_IS*         pcis = (PC_IS*)(pc->data);
175   IS             dirIS = NULL;
176   PetscInt       i;
177   PetscErrorCode ierr;
178 
179   PetscFunctionBegin;
180   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
181   if (zerodiag) {
182     Mat            A;
183     Vec            vec3_N;
184     PetscScalar    *vals;
185     const PetscInt *idxs;
186     PetscInt       nz;
187 
188     /* p0 */
189     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
190     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
191     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
192     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
193     for (i=0;i<nz;i++) vals[i] = 1.;
194     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
195     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
196     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
197     /* v_I */
198     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
199     for (i=0;i<nz;i++) vals[i] = 0.;
200     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
201     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
202     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
203     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
204     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
205     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
206     if (dirIS) {
207       PetscInt n;
208 
209       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
210       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
211       for (i=0;i<n;i++) vals[i] = 0.;
212       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
213       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
214     }
215     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
216     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
217     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
218     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
219     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
220     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
221     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
222     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) {
223       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %f (should be numerically 0.)",PetscAbsScalar(vals[0]));
224     }
225     ierr = PetscFree(vals);CHKERRQ(ierr);
226     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
227   }
228   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
229 
230   /* check PCBDDCBenignGetOrSetP0 */
231   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
232   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
233   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
234   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
235   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
236   for (i=0;i<pcbddc->benign_n;i++) {
237     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
238       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %1.4e at %d instead of %1.4e\n",pcbddc->benign_p0[i],i,-PetscGlobalRank-i);CHKERRQ(ierr);
239     }
240   }
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
246 PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
247 {
248   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
249   IS             pressures,zerodiag,*zerodiag_subs;
250   PetscInt       nz,n;
251   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
252   PetscErrorCode ierr;
253 
254   PetscFunctionBegin;
255   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
256   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
257   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
258   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
259   pcbddc->benign_original_mat = pcbddc->local_mat;
260   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
261      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
262      Checks if all the pressure dofs in each subdomain have a zero diagonal
263      If not, a change of basis on pressures is not needed
264      since the local Schur complements are SPD
265   */
266   has_null_pressures = PETSC_TRUE;
267   have_null = PETSC_TRUE;
268   if (pcbddc->n_ISForDofsLocal) {
269     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
270 
271     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
272     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
273     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
274     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
275     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
276     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
277     if (!sorted) {
278       ierr = ISSort(pressures);CHKERRQ(ierr);
279     }
280   } else {
281     pressures = NULL;
282   }
283   ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
284   /* TODO: add check for shared dofs and raise error */
285   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
286   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
287   if (!sorted) {
288     ierr = ISSort(zerodiag);CHKERRQ(ierr);
289   }
290   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
291   if (!nz) {
292     if (n) have_null = PETSC_FALSE;
293     has_null_pressures = PETSC_FALSE;
294     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
295   }
296   recompute_zerodiag = PETSC_FALSE;
297   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
298   zerodiag_subs = NULL;
299   pcbddc->benign_n = 0;
300   if (has_null_pressures) {
301     IS       *subs;
302     PetscInt nsubs,i;
303 
304     subs = pcbddc->local_subs;
305     nsubs = pcbddc->n_local_subs;
306     if (nsubs > 1) {
307       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
308       for (i=0;i<nsubs;i++) {
309         ISLocalToGlobalMapping l2g;
310         IS                     t_zerodiag_subs;
311         PetscInt               nl;
312 
313         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
314         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
315         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
316         if (nl) {
317           PetscBool valid = PETSC_TRUE;
318 
319           if (pressures) {
320             IS t_pressure_subs;
321             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
322             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
323             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
324           }
325           if (valid) {
326             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
327             pcbddc->benign_n++;
328           } else {
329             recompute_zerodiag = PETSC_TRUE;
330           }
331         }
332         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
333         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
334       }
335     } else { /* there's just one subdomain (or zero if they have not been detected */
336       PetscBool valid = PETSC_TRUE;
337       if (pressures) {
338         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
339       }
340       if (valid) {
341         pcbddc->benign_n = 1;
342         ierr = PetscCalloc1(1,&zerodiag_subs);CHKERRQ(ierr);
343         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
344         zerodiag_subs[0] = zerodiag;
345       }
346     }
347   }
348 
349   if (!pcbddc->benign_n) {
350     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
351     recompute_zerodiag = PETSC_FALSE;
352     has_null_pressures = PETSC_FALSE;
353     have_null = PETSC_FALSE;
354   }
355 
356   /* final check for null pressures */
357   if (zerodiag && pressures) {
358     PetscInt nz,np;
359     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
360     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
361     if (nz != np) have_null = PETSC_FALSE;
362   }
363 
364   if (recompute_zerodiag) {
365     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
366     if (pcbddc->benign_n == 1) {
367       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
368       zerodiag = zerodiag_subs[0];
369     } else {
370       PetscInt i,nzn,*new_idxs;
371 
372       nzn = 0;
373       for (i=0;i<pcbddc->benign_n;i++) {
374         PetscInt ns;
375         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
376         nzn += ns;
377       }
378       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
379       nzn = 0;
380       for (i=0;i<pcbddc->benign_n;i++) {
381         PetscInt ns,*idxs;
382         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
383         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
384         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
385         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
386         nzn += ns;
387       }
388       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
389       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
390     }
391     have_null = PETSC_FALSE;
392   }
393 
394   if (has_null_pressures) {
395     IS             zerodiagc;
396     const PetscInt *idxs,*idxsc;
397     PetscInt       i,s,*nnz;
398     Mat            M;
399 
400     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
401     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
402     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
403     /* local change of basis for pressures */
404     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
405     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
406     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
407     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
408     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
409     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
410     for (i=0;i<pcbddc->benign_n;i++) {
411       PetscInt nzs,j;
412 
413       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
414       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
415       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
416       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
417       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
418     }
419     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
420     ierr = PetscFree(nnz);CHKERRQ(ierr);
421     /* set identity on velocities */
422     for (i=0;i<n-nz;i++) {
423       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
424     }
425     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
426     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
427     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
428     ierr = PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0);CHKERRQ(ierr);
429     /* set change on pressures */
430     for (s=0;s<pcbddc->benign_n;s++) {
431       PetscScalar *array;
432       PetscInt    nzs;
433 
434       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
435       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
436       for (i=0;i<nzs-1;i++) {
437         PetscScalar vals[2];
438         PetscInt    cols[2];
439 
440         cols[0] = idxs[i];
441         cols[1] = idxs[nzs-1];
442         vals[0] = 1.;
443         vals[1] = 1.;
444         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
445       }
446       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
447       for (i=0;i<nzs-1;i++) array[i] = -1.;
448       array[nzs-1] = 1.;
449       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
450       /* store local idxs for p0 */
451       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
452       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
453       ierr = ISDestroy(&zerodiag_subs[s]);CHKERRQ(ierr);
454       ierr = PetscFree(array);CHKERRQ(ierr);
455     }
456     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
457     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
458     /* TODO: need optimization? */
459     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
460     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
461     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
462     ierr = MatDestroy(&M);CHKERRQ(ierr);
463     /* store global idxs for p0 */
464     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
465   }
466   ierr = PetscFree(zerodiag_subs);CHKERRQ(ierr);
467   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
468 
469   /* determines if the coarse solver will be singular or not */
470   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
471   *zerodiaglocal = zerodiag;
472   PetscFunctionReturn(0);
473 }
474 
475 #undef __FUNCT__
476 #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
477 PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
478 {
479   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
480   PetscErrorCode ierr;
481 
482   PetscFunctionBegin;
483   if (!pcbddc->benign_sf) {
484     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
485     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
486   }
487   if (get) { /* use SF to get values */
488     PetscScalar *array;
489 
490     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
491     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
492     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
493     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
494   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
495     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
496     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
497     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
498   }
499   PetscFunctionReturn(0);
500 }
501 
502 #undef __FUNCT__
503 #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
504 PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
505 {
506   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
507   PetscErrorCode ierr;
508 
509   PetscFunctionBegin;
510   /* TODO: add error checking
511     - avoid nested pop (or push) calls.
512     - cannot push before pop.
513     - cannot call this if pcbddc->local_mat is NULL
514   */
515   if (!pcbddc->benign_n) {
516     PetscFunctionReturn(0);
517   }
518   if (pop) {
519     IS       is_p0;
520     MatReuse reuse;
521 
522     /* extract B_0 */
523     reuse = MAT_INITIAL_MATRIX;
524     if (pcbddc->benign_B0) {
525       reuse = MAT_REUSE_MATRIX;
526     }
527     ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
528     ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
529     /* remove rows and cols from local problem */
530     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
531     ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
532     ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
533   } else { /* push */
534     PetscInt i;
535 
536     for (i=0;i<pcbddc->benign_n;i++) {
537       PetscScalar *B0_vals;
538       PetscInt    *B0_cols,B0_ncol;
539 
540       ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
541       ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
542       ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+1,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
543       ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
544       ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
545     }
546     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
547     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
548   }
549   PetscFunctionReturn(0);
550 }
551 
552 #undef __FUNCT__
553 #define __FUNCT__ "PCBDDCAdaptiveSelection"
554 PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
555 {
556   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
557   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
558   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
559   PetscBLASInt    *B_iwork,*B_ifail;
560   PetscScalar     *work,lwork;
561   PetscScalar     *St,*S,*eigv;
562   PetscScalar     *Sarray,*Starray;
563   PetscReal       *eigs,thresh;
564   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
565   PetscBool       allocated_S_St;
566 #if defined(PETSC_USE_COMPLEX)
567   PetscReal       *rwork;
568 #endif
569   PetscErrorCode  ierr;
570 
571   PetscFunctionBegin;
572   if (!sub_schurs->use_mumps) {
573     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
574   }
575 
576   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
577     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);
578   }
579 
580   if (pcbddc->dbg_flag) {
581     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
582     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
583     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
584     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
585   }
586 
587   if (pcbddc->dbg_flag) {
588     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %d (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef);
589   }
590 
591   /* max size of subsets */
592   mss = 0;
593   for (i=0;i<sub_schurs->n_subs;i++) {
594     PetscInt subset_size;
595 
596     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
597     mss = PetscMax(mss,subset_size);
598   }
599 
600   /* min/max and threshold */
601   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
602   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
603   nmax = PetscMax(nmin,nmax);
604   allocated_S_St = PETSC_FALSE;
605   if (nmin) {
606     allocated_S_St = PETSC_TRUE;
607   }
608 
609   /* allocate lapack workspace */
610   cum = cum2 = 0;
611   maxneigs = 0;
612   for (i=0;i<sub_schurs->n_subs;i++) {
613     PetscInt n,subset_size;
614 
615     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
616     n = PetscMin(subset_size,nmax);
617     cum += subset_size;
618     cum2 += subset_size*n;
619     maxneigs = PetscMax(maxneigs,n);
620   }
621   if (mss) {
622     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
623       PetscBLASInt B_itype = 1;
624       PetscBLASInt B_N = mss;
625       PetscReal    zero = 0.0;
626       PetscReal    eps = 0.0; /* dlamch? */
627 
628       B_lwork = -1;
629       S = NULL;
630       St = NULL;
631       eigs = NULL;
632       eigv = NULL;
633       B_iwork = NULL;
634       B_ifail = NULL;
635 #if defined(PETSC_USE_COMPLEX)
636       rwork = NULL;
637 #endif
638       thresh = 1.0;
639       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
640 #if defined(PETSC_USE_COMPLEX)
641       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));
642 #else
643       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));
644 #endif
645       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
646       ierr = PetscFPTrapPop();CHKERRQ(ierr);
647     } else {
648         /* TODO */
649     }
650   } else {
651     lwork = 0;
652   }
653 
654   nv = 0;
655   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) */
656     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
657   }
658   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
659   if (allocated_S_St) {
660     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
661   }
662   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
663 #if defined(PETSC_USE_COMPLEX)
664   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
665 #endif
666   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
667                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
668                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
669                       nv+cum,&pcbddc->adaptive_constraints_idxs,
670                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
671   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
672 
673   maxneigs = 0;
674   cum = cum2 = cumarray = 0;
675   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
676   pcbddc->adaptive_constraints_data_ptr[0] = 0;
677   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
678     const PetscInt *idxs;
679 
680     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
681     for (cum=0;cum<nv;cum++) {
682       pcbddc->adaptive_constraints_n[cum] = 1;
683       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
684       pcbddc->adaptive_constraints_data[cum] = 1.0;
685       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
686       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
687     }
688     cum2 = cum;
689     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
690   }
691 
692   if (mss) { /* multilevel */
693     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
694     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
695   }
696 
697   thresh = pcbddc->adaptive_threshold;
698   for (i=0;i<sub_schurs->n_subs;i++) {
699     const PetscInt *idxs;
700     PetscReal      infty = PETSC_MAX_REAL;
701     PetscInt       j,subset_size,eigs_start = 0;
702     PetscBLASInt   B_N;
703     PetscBool      same_data = PETSC_FALSE;
704 
705     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
706     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
707     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
708     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
709       if (sub_schurs->is_hermitian) {
710         PetscInt j,k;
711         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
712           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
713           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
714         }
715         for (j=0;j<subset_size;j++) {
716           for (k=j;k<subset_size;k++) {
717             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
718             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
719           }
720         }
721       } else {
722         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
723         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
724       }
725     } else {
726       S = Sarray + cumarray;
727       St = Starray + cumarray;
728     }
729 
730     /* see if we can save some work */
731     if (sub_schurs->n_subs == 1) {
732       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
733     }
734 
735     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
736       B_neigs = 0;
737     } else {
738       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
739         PetscBLASInt B_itype = 1;
740         PetscBLASInt B_IL, B_IU;
741         PetscReal    eps = -1.0; /* dlamch? */
742         PetscInt     nmin_s;
743 
744         if (pcbddc->dbg_flag) {
745           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]]);
746         }
747 
748         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
749         if (thresh > 1.+PETSC_SMALL) {
750 
751           /* ask for eigenvalues larger than thresh */
752 #if defined(PETSC_USE_COMPLEX)
753           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
754 #else
755           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
756 #endif
757         } else {
758           B_IU = PetscMax(1,PetscMin(B_N,nmax));
759           B_IL = 1;
760 #if defined(PETSC_USE_COMPLEX)
761           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
762 #else
763           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
764 #endif
765         }
766         ierr = PetscFPTrapPop();CHKERRQ(ierr);
767         if (B_ierr) {
768           if (B_ierr < 0 ) {
769             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
770           } else if (B_ierr <= B_N) {
771             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
772           } else {
773             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);
774           }
775         }
776 
777         if (B_neigs > nmax) {
778           if (pcbddc->dbg_flag) {
779             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
780           }
781           eigs_start = B_neigs -nmax;
782           B_neigs = nmax;
783         }
784 
785         nmin_s = PetscMin(nmin,B_N);
786         if (B_neigs < nmin_s) {
787           PetscBLASInt B_neigs2;
788 
789           B_IU = B_N - B_neigs;
790           B_IL = B_N - nmin_s + 1;
791           if (pcbddc->dbg_flag) {
792             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);
793           }
794           if (sub_schurs->is_hermitian) {
795             PetscInt j;
796             for (j=0;j<subset_size;j++) {
797               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
798             }
799             for (j=0;j<subset_size;j++) {
800               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
801             }
802           } else {
803             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
804             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
805           }
806           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
807 #if defined(PETSC_USE_COMPLEX)
808           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&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));
809 #else
810           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&thresh,&infty,&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));
811 #endif
812           ierr = PetscFPTrapPop();CHKERRQ(ierr);
813           B_neigs += B_neigs2;
814         }
815         if (B_ierr) {
816           if (B_ierr < 0 ) {
817             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
818           } else if (B_ierr <= B_N) {
819             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
820           } else {
821             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);
822           }
823         }
824         if (pcbddc->dbg_flag) {
825           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
826           for (j=0;j<B_neigs;j++) {
827             if (eigs[j] == 0.0) {
828               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
829             } else {
830               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
831             }
832           }
833         }
834       } else {
835           /* TODO */
836       }
837     }
838     maxneigs = PetscMax(B_neigs,maxneigs);
839     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
840     if (B_neigs) {
841       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);
842 
843       if (pcbddc->dbg_flag > 1) {
844         PetscInt ii;
845         for (ii=0;ii<B_neigs;ii++) {
846           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
847           for (j=0;j<B_N;j++) {
848 #if defined(PETSC_USE_COMPLEX)
849             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
850             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
851             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
852 #else
853             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);CHKERRQ(ierr);
854 #endif
855           }
856         }
857       }
858 #if 0
859       for (j=0;j<B_neigs;j++) {
860         PetscBLASInt Blas_N,Blas_one = 1.0;
861         PetscScalar norm;
862         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
863         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
864                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
865         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
866           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
867         } else {
868           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
869         }
870         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
871       }
872 #endif
873       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
874       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
875       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
876       cum++;
877     }
878     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
879     /* shift for next computation */
880     cumarray += subset_size*subset_size;
881   }
882   if (pcbddc->dbg_flag) {
883     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
884   }
885 
886   if (mss) {
887     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
888     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
889     /* destroy matrices (junk) */
890     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
891     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
892   }
893   if (allocated_S_St) {
894     ierr = PetscFree2(S,St);CHKERRQ(ierr);
895   }
896   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
897 #if defined(PETSC_USE_COMPLEX)
898   ierr = PetscFree(rwork);CHKERRQ(ierr);
899 #endif
900   if (pcbddc->dbg_flag) {
901     PetscInt maxneigs_r;
902     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
903     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
904   }
905   PetscFunctionReturn(0);
906 }
907 
908 #undef __FUNCT__
909 #define __FUNCT__ "PCBDDCSetUpSolvers"
910 PetscErrorCode PCBDDCSetUpSolvers(PC pc)
911 {
912   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
913   PetscScalar    *coarse_submat_vals;
914   PetscErrorCode ierr;
915 
916   PetscFunctionBegin;
917   /* Setup local scatters R_to_B and (optionally) R_to_D */
918   /* PCBDDCSetUpLocalWorkVectors should be called first! */
919   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
920 
921   /* Setup local neumann solver ksp_R */
922   /* PCBDDCSetUpLocalScatters should be called first! */
923   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
924 
925   /* Change global null space passed in by the user if change of basis has been requested */
926   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
927     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
928   }
929 
930   /*
931      Setup local correction and local part of coarse basis.
932      Gives back the dense local part of the coarse matrix in column major ordering
933   */
934   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
935 
936   /* Compute total number of coarse nodes and setup coarse solver */
937   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
938 
939   /* free */
940   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
941   PetscFunctionReturn(0);
942 }
943 
944 #undef __FUNCT__
945 #define __FUNCT__ "PCBDDCResetCustomization"
946 PetscErrorCode PCBDDCResetCustomization(PC pc)
947 {
948   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
949   PetscErrorCode ierr;
950 
951   PetscFunctionBegin;
952   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
953   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
954   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
955   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
956   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
957   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
958   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
959   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
960   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
961   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
962   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
963   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
964   PetscFunctionReturn(0);
965 }
966 
967 #undef __FUNCT__
968 #define __FUNCT__ "PCBDDCResetTopography"
969 PetscErrorCode PCBDDCResetTopography(PC pc)
970 {
971   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
972   PetscInt       i;
973   PetscErrorCode ierr;
974 
975   PetscFunctionBegin;
976   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
977   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
978   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
979   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
980   for (i=0;i<pcbddc->n_local_subs;i++) {
981     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
982   }
983   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
984   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
985   PetscFunctionReturn(0);
986 }
987 
988 #undef __FUNCT__
989 #define __FUNCT__ "PCBDDCResetSolvers"
990 PetscErrorCode PCBDDCResetSolvers(PC pc)
991 {
992   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
993   PetscScalar    *array;
994   PetscErrorCode ierr;
995 
996   PetscFunctionBegin;
997   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
998   if (pcbddc->coarse_phi_B) {
999     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
1000     ierr = PetscFree(array);CHKERRQ(ierr);
1001   }
1002   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1003   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1004   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1005   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1006   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1007   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1008   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
1009   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1010   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1011   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1012   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1013   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1014   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1015   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1016   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1017   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1018   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1019   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1020   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
1021   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1022   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
1023   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
1024   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
1025   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
1026   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
1027   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
1028   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
1029   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1030   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1031   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1032   PetscFunctionReturn(0);
1033 }
1034 
1035 #undef __FUNCT__
1036 #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1037 PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
1038 {
1039   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1040   PC_IS          *pcis = (PC_IS*)pc->data;
1041   VecType        impVecType;
1042   PetscInt       n_constraints,n_R,old_size;
1043   PetscErrorCode ierr;
1044 
1045   PetscFunctionBegin;
1046   if (!pcbddc->ConstraintMatrix) {
1047     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1048   }
1049   /* get sizes */
1050   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1051   n_R = pcis->n - pcbddc->n_vertices;
1052   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1053   /* local work vectors (try to avoid unneeded work)*/
1054   /* R nodes */
1055   old_size = -1;
1056   if (pcbddc->vec1_R) {
1057     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1058   }
1059   if (n_R != old_size) {
1060     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1061     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1062     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
1063     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
1064     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1065     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1066   }
1067   /* local primal dofs */
1068   old_size = -1;
1069   if (pcbddc->vec1_P) {
1070     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1071   }
1072   if (pcbddc->local_primal_size != old_size) {
1073     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1074     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1075     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
1076     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1077   }
1078   /* local explicit constraints */
1079   old_size = -1;
1080   if (pcbddc->vec1_C) {
1081     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1082   }
1083   if (n_constraints && n_constraints != old_size) {
1084     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1085     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
1086     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
1087     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
1088   }
1089   PetscFunctionReturn(0);
1090 }
1091 
1092 #undef __FUNCT__
1093 #define __FUNCT__ "PCBDDCSetUpCorrection"
1094 PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
1095 {
1096   PetscErrorCode  ierr;
1097   /* pointers to pcis and pcbddc */
1098   PC_IS*          pcis = (PC_IS*)pc->data;
1099   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1100   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
1101   /* submatrices of local problem */
1102   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1103   /* submatrices of benign trick */
1104   Mat             B0_V = NULL;
1105   /* submatrices of local coarse problem */
1106   Mat             S_VV,S_CV,S_VC,S_CC;
1107   /* working matrices */
1108   Mat             C_CR;
1109   /* additional working stuff */
1110   PC              pc_R;
1111   Mat             F;
1112   PetscBool       isLU,isCHOL,isILU;
1113 
1114   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
1115   PetscScalar     *work;
1116   PetscInt        *idx_V_B;
1117   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
1118   PetscInt        i,n_R,n_D,n_B;
1119 
1120   /* some shortcuts to scalars */
1121   PetscScalar     one=1.0,m_one=-1.0;
1122 
1123   PetscFunctionBegin;
1124   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1125     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1126   }
1127 
1128   /* Set Non-overlapping dimensions */
1129   n_vertices = pcbddc->n_vertices;
1130   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1131   n_B = pcis->n_B;
1132   n_D = pcis->n - n_B;
1133   n_R = pcis->n - n_vertices;
1134 
1135   /* vertices in boundary numbering */
1136   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
1137   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
1138   if (i != n_vertices) {
1139     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1140   }
1141 
1142   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1143   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
1144   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
1145   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
1146   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
1147   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
1148   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
1149   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
1150   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
1151   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
1152 
1153   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
1154   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
1155   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
1156   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
1157   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1158   lda_rhs = n_R;
1159   if (isLU || isILU || isCHOL) {
1160     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1161   } else if (sub_schurs->reuse_mumps) {
1162     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1163     MatFactorType type;
1164 
1165     F = reuse_mumps->F;
1166     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1167     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1168     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
1169   } else {
1170     F = NULL;
1171   }
1172 
1173   /* allocate workspace */
1174   n = 0;
1175   if (n_constraints) {
1176     n += lda_rhs*n_constraints;
1177   }
1178   if (n_vertices) {
1179     n = PetscMax(2*lda_rhs*n_vertices,n);
1180     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1181   }
1182   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1183 
1184   /* Precompute stuffs needed for preprocessing and application of BDDC*/
1185   if (n_constraints) {
1186     Mat         M1,M2,M3;
1187     Mat         auxmat;
1188     IS          is_aux;
1189     PetscScalar *array,*array2;
1190 
1191     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1192     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
1193 
1194     /* Extract constraints on R nodes: C_{CR}  */
1195     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
1196     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
1197     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
1198 
1199     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
1200     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1201     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
1202     for (i=0;i<n_constraints;i++) {
1203       const PetscScalar *row_cmat_values;
1204       const PetscInt    *row_cmat_indices;
1205       PetscInt          size_of_constraint,j;
1206 
1207       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
1208       for (j=0;j<size_of_constraint;j++) {
1209         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
1210       }
1211       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
1212     }
1213     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
1214     if (F) {
1215       Mat B;
1216 
1217       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1218       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1219       ierr = MatDestroy(&B);CHKERRQ(ierr);
1220     } else {
1221       PetscScalar *marr;
1222 
1223       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1224       for (i=0;i<n_constraints;i++) {
1225         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1226         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
1227         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1228         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1229         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
1230       }
1231       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1232     }
1233     if (!pcbddc->switch_static) {
1234       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1235       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
1236       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
1237       for (i=0;i<n_constraints;i++) {
1238         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
1239         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
1240         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1241         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1242         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
1243         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1244       }
1245       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
1246       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
1247       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
1248     } else {
1249       if (lda_rhs != n_R) {
1250         IS dummy;
1251 
1252         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
1253         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,dummy,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1254         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1255       } else {
1256         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
1257         pcbddc->local_auxmat2 = local_auxmat2_R;
1258       }
1259       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
1260     }
1261     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
1262     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
1263     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
1264     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
1265     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
1266     if (isCHOL) {
1267       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
1268     } else {
1269       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
1270     }
1271     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
1272     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
1273     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
1274     ierr = MatDestroy(&M2);CHKERRQ(ierr);
1275     ierr = MatDestroy(&M3);CHKERRQ(ierr);
1276     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
1277     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
1278     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
1279     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
1280     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1281   }
1282   /* Get submatrices from subdomain matrix */
1283   if (pcbddc->benign_n) {
1284     IS        dummy;
1285     Mat       B0_R;
1286     PetscReal norm;
1287 
1288     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
1289     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1290     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1291     if (norm > PETSC_SMALL) {
1292       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1293     }
1294     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1295     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1296   }
1297 
1298   if (n_vertices) {
1299     IS is_aux;
1300 
1301     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
1302       IS tis;
1303 
1304       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
1305       ierr = ISSort(tis);CHKERRQ(ierr);
1306       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
1307       ierr = ISDestroy(&tis);CHKERRQ(ierr);
1308     } else {
1309       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
1310     }
1311     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1312     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1313     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1314     if (pcbddc->benign_n) {
1315       IS dummy;
1316 
1317       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
1318       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1319       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1320     }
1321     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
1322   }
1323 
1324   /* Matrix of coarse basis functions (local) */
1325   if (pcbddc->coarse_phi_B) {
1326     PetscInt on_B,on_primal,on_D=n_D;
1327     if (pcbddc->coarse_phi_D) {
1328       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
1329     }
1330     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
1331     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
1332       PetscScalar *marray;
1333 
1334       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
1335       ierr = PetscFree(marray);CHKERRQ(ierr);
1336       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1337       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1338       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1339       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1340     }
1341   }
1342 
1343   if (!pcbddc->coarse_phi_B) {
1344     PetscScalar *marray;
1345 
1346     n = n_B*pcbddc->local_primal_size;
1347     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1348       n += n_D*pcbddc->local_primal_size;
1349     }
1350     if (!pcbddc->symmetric_primal) {
1351       n *= 2;
1352     }
1353     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
1354     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1355     n = n_B*pcbddc->local_primal_size;
1356     if (pcbddc->switch_static || pcbddc->dbg_flag) {
1357       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1358       n += n_D*pcbddc->local_primal_size;
1359     }
1360     if (!pcbddc->symmetric_primal) {
1361       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1362       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1363         n = n_B*pcbddc->local_primal_size;
1364         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1365       }
1366     } else {
1367       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1368       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
1369       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1370         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1371         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1372       }
1373     }
1374   }
1375 
1376   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
1377   p0_lidx_I = NULL;
1378   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1379     const PetscInt *idxs;
1380 
1381     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1382     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
1383     for (i=0;i<pcbddc->benign_n;i++) {
1384       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
1385     }
1386     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1387   }
1388 
1389   /* vertices */
1390   if (n_vertices) {
1391 
1392     ierr = MatConvert(A_VV,MATDENSE,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
1393 
1394     if (n_R) {
1395       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
1396       PetscBLASInt B_N,B_one = 1;
1397       PetscScalar  *x,*y;
1398       PetscBool    isseqaij;
1399 
1400       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
1401       if (lda_rhs == n_R) {
1402         ierr = MatConvert(A_RV,MATDENSE,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1403       } else {
1404         Mat         A_RVt;
1405         PetscScalar *array;
1406 
1407         /* TODO optimize */
1408         ierr = MatConvert(A_RV,MATDENSE,MAT_INITIAL_MATRIX,&A_RVt);CHKERRQ(ierr);
1409         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1410         ierr = PetscMemzero(work+lda_rhs*n_vertices,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1411         ierr = MatDenseGetArray(A_RVt,&array);CHKERRQ(ierr);
1412         for (i=0;i<n_vertices;i++) {
1413           ierr = PetscMemcpy(work+(n_vertices+i)*lda_rhs,array+i*n_R,n_R*sizeof(PetscScalar));CHKERRQ(ierr);
1414         }
1415         ierr = MatDenseRestoreArray(A_RVt,&array);CHKERRQ(ierr);
1416         ierr = MatDestroy(&A_RVt);CHKERRQ(ierr);
1417         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&A_RV);CHKERRQ(ierr);
1418       }
1419       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1420       if (F) { /* TODO could be optimized for symmetric problems */
1421         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
1422       } else {
1423         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
1424         for (i=0;i<n_vertices;i++) {
1425           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
1426           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
1427           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1428           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1429           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
1430         }
1431         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
1432       }
1433       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1434       /* S_VV and S_CV */
1435       if (n_constraints) {
1436         Mat B;
1437 
1438         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1439         for (i=0;i<n_vertices;i++) {
1440           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1441           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
1442           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1443           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1444           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
1445           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1446         }
1447         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
1448         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
1449         ierr = MatDestroy(&B);CHKERRQ(ierr);
1450         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
1451         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
1452         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
1453         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
1454         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
1455         ierr = MatDestroy(&B);CHKERRQ(ierr);
1456       }
1457       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1458       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
1459         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
1460       }
1461       if (lda_rhs != n_R) {
1462         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1463         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1464         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
1465       }
1466       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
1467       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1468       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
1469       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
1470       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
1471       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
1472       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
1473       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
1474       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1475       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1476     } else {
1477       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1478     }
1479     for (i=0;i<pcbddc->benign_n;i++) {
1480       const PetscScalar *vals;
1481       const PetscInt    *idxs;
1482       PetscInt          n,j,primal_idx;
1483 
1484       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
1485       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1486       for (j=0;j<n;j++) {
1487         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
1488         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1489       }
1490       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
1491     }
1492     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1493 
1494     /* coarse basis functions */
1495     for (i=0;i<n_vertices;i++) {
1496       PetscScalar *y;
1497 
1498       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
1499       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
1500       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
1501       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1502       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1503       y[n_B*i+idx_V_B[i]] = 1.0;
1504       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
1505       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
1506 
1507       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1508         PetscInt j;
1509 
1510         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
1511         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
1512         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1513         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1514         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1515         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
1516         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
1517       }
1518       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1519     }
1520     /* if n_R == 0 the object is not destroyed */
1521     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1522   }
1523 
1524   if (n_constraints) {
1525     Mat B;
1526 
1527     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1528     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
1529     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
1530     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
1531     if (n_vertices) {
1532       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
1533         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
1534       } else {
1535         Mat S_VCt;
1536 
1537         if (lda_rhs != n_R) {
1538           ierr = MatDestroy(&B);CHKERRQ(ierr);
1539           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B);CHKERRQ(ierr);
1540           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
1541         }
1542         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
1543         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1544         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
1545       }
1546     }
1547     ierr = MatDestroy(&B);CHKERRQ(ierr);
1548     /* coarse basis functions */
1549     for (i=0;i<n_constraints;i++) {
1550       PetscScalar *y;
1551 
1552       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
1553       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
1554       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
1555       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1556       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1557       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
1558       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
1559       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1560         PetscInt j;
1561 
1562         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
1563         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
1564         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1565         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1566         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1567         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
1568         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
1569       }
1570       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1571     }
1572   }
1573   if (n_constraints) {
1574     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
1575   }
1576   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1577   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1578 
1579   /* compute other basis functions for non-symmetric problems */
1580   if (!pcbddc->symmetric_primal) {
1581     Mat         B_V=NULL,B_C=NULL;
1582     PetscScalar *marray;
1583 
1584     if (n_constraints) {
1585       Mat S_CCT,C_CRT;
1586 
1587       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
1588       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
1589       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
1590       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
1591       if (n_vertices) {
1592         Mat S_VCT;
1593 
1594         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
1595         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
1596         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
1597       }
1598       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
1599     }
1600     if (n_vertices && n_R) {
1601       PetscScalar    *av,*marray;
1602       const PetscInt *xadj,*adjncy;
1603       PetscInt       n;
1604       PetscBool      flg_row;
1605 
1606       /* B_V = B_V - A_VR^T */
1607       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
1608       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1609       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
1610       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1611       for (i=0;i<n;i++) {
1612         PetscInt j;
1613         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
1614       }
1615       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1616       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1617       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1618     }
1619 
1620     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
1621     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1622     for (i=0;i<n_vertices;i++) {
1623       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
1624       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
1625       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1626       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1627       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
1628     }
1629     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1630     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
1631     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
1632       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
1633       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
1634       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1635       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1636       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
1637     }
1638     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
1639     /* coarse basis functions */
1640     for (i=0;i<pcbddc->local_primal_size;i++) {
1641       PetscScalar *y;
1642 
1643       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
1644       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
1645       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
1646       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1647       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1648       if (i<n_vertices) {
1649         y[n_B*i+idx_V_B[i]] = 1.0;
1650       }
1651       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
1652       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
1653 
1654       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1655         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
1656         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
1657         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1658         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1659         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
1660         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
1661       }
1662       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1663     }
1664     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
1665     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
1666   }
1667   /* free memory */
1668   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
1669   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
1670   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
1671   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
1672   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1673   ierr = PetscFree(work);CHKERRQ(ierr);
1674   if (n_vertices) {
1675     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1676   }
1677   if (n_constraints) {
1678     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1679   }
1680   /* Checking coarse_sub_mat and coarse basis functios */
1681   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1682   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1683   if (pcbddc->dbg_flag) {
1684     Mat         coarse_sub_mat;
1685     Mat         AUXMAT,TM1,TM2,TM3,TM4;
1686     Mat         coarse_phi_D,coarse_phi_B;
1687     Mat         coarse_psi_D,coarse_psi_B;
1688     Mat         A_II,A_BB,A_IB,A_BI;
1689     Mat         C_B,CPHI;
1690     IS          is_dummy;
1691     Vec         mones;
1692     MatType     checkmattype=MATSEQAIJ;
1693     PetscReal   real_value;
1694 
1695     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1696     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1697     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1698     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1699     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1700     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1701     if (!pcbddc->symmetric_primal) {
1702       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
1703       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
1704     }
1705     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1706 
1707     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1708     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
1709     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1710     if (!pcbddc->symmetric_primal) {
1711       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1712       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
1713       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1714       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1715       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
1716       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1717       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1718       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
1719       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1720       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1721       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
1722       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1723     } else {
1724       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
1725       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
1726       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1727       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
1728       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1729       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1730       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
1731       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1732     }
1733     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1734     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1735     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1736     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
1737     if (pcbddc->benign_n) {
1738       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
1739       PetscScalar *data,*data2;
1740       PetscInt    j;
1741 
1742       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
1743       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
1744       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1745       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1746       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1747       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1748       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
1749       for (j=0;j<pcbddc->benign_n;j++) {
1750         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
1751         for (i=0;i<pcbddc->local_primal_size;i++) {
1752           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
1753           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
1754         }
1755       }
1756       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1757       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1758       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1759       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1760       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1761       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1762       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1763       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1764       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1765     }
1766 #if 0
1767   {
1768     PetscViewer viewer;
1769     char filename[256];
1770     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
1771     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1772     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1773     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
1774     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
1775     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
1776     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1777     ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
1778     ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
1779     if (pcbddc->coarse_phi_D) {
1780       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
1781       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
1782     }
1783     if (pcbddc->coarse_psi_B) {
1784       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
1785       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
1786     }
1787     if (pcbddc->coarse_phi_B) {
1788       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
1789       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
1790     }
1791     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1792   }
1793 #endif
1794     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1795     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1796     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1797     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1798 
1799     /* check constraints */
1800     if (!pcbddc->benign_n) { /* TODO: add benign case */
1801       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
1802       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
1803       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1804       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
1805       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1806       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1807       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1808       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1809       if (!pcbddc->symmetric_primal) {
1810         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1811         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1812         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1813         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1814         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1815       }
1816       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
1817       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
1818       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1819       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1820     }
1821     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1822     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
1823     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
1824     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
1825     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
1826     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
1827     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
1828     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
1829     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
1830     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
1831     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1832     if (!pcbddc->symmetric_primal) {
1833       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
1834       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
1835     }
1836     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
1837   }
1838   /* get back data */
1839   *coarse_submat_vals_n = coarse_submat_vals;
1840   PetscFunctionReturn(0);
1841 }
1842 
1843 #undef __FUNCT__
1844 #define __FUNCT__ "MatGetSubMatrixUnsorted"
1845 PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1846 {
1847   Mat            *work_mat;
1848   IS             isrow_s,iscol_s;
1849   PetscBool      rsorted,csorted;
1850   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1851   PetscErrorCode ierr;
1852 
1853   PetscFunctionBegin;
1854   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1855   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1856   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1857   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1858 
1859   if (!rsorted) {
1860     const PetscInt *idxs;
1861     PetscInt *idxs_sorted,i;
1862 
1863     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1864     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1865     for (i=0;i<rsize;i++) {
1866       idxs_perm_r[i] = i;
1867     }
1868     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1869     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1870     for (i=0;i<rsize;i++) {
1871       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1872     }
1873     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1874     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1875   } else {
1876     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1877     isrow_s = isrow;
1878   }
1879 
1880   if (!csorted) {
1881     if (isrow == iscol) {
1882       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1883       iscol_s = isrow_s;
1884     } else {
1885       const PetscInt *idxs;
1886       PetscInt *idxs_sorted,i;
1887 
1888       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1889       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1890       for (i=0;i<csize;i++) {
1891         idxs_perm_c[i] = i;
1892       }
1893       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1894       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1895       for (i=0;i<csize;i++) {
1896         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1897       }
1898       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1899       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1900     }
1901   } else {
1902     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1903     iscol_s = iscol;
1904   }
1905 
1906   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1907 
1908   if (!rsorted || !csorted) {
1909     Mat      new_mat;
1910     IS       is_perm_r,is_perm_c;
1911 
1912     if (!rsorted) {
1913       PetscInt *idxs_r,i;
1914       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1915       for (i=0;i<rsize;i++) {
1916         idxs_r[idxs_perm_r[i]] = i;
1917       }
1918       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1919       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1920     } else {
1921       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1922     }
1923     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1924 
1925     if (!csorted) {
1926       if (isrow_s == iscol_s) {
1927         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1928         is_perm_c = is_perm_r;
1929       } else {
1930         PetscInt *idxs_c,i;
1931         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1932         for (i=0;i<csize;i++) {
1933           idxs_c[idxs_perm_c[i]] = i;
1934         }
1935         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1936         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1937       }
1938     } else {
1939       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1940     }
1941     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1942 
1943     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1944     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1945     work_mat[0] = new_mat;
1946     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1947     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1948   }
1949 
1950   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1951   *B = work_mat[0];
1952   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1953   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1954   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1955   PetscFunctionReturn(0);
1956 }
1957 
1958 #undef __FUNCT__
1959 #define __FUNCT__ "PCBDDCComputeLocalMatrix"
1960 PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1961 {
1962   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
1963   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1964   Mat            new_mat;
1965   IS             is_local,is_global;
1966   PetscInt       local_size;
1967   PetscBool      isseqaij;
1968   PetscErrorCode ierr;
1969 
1970   PetscFunctionBegin;
1971   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1972   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
1973   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1974   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1975   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1976   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1977   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1978 
1979   /* check */
1980   if (pcbddc->dbg_flag) {
1981     Vec       x,x_change;
1982     PetscReal error;
1983 
1984     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1985     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
1986     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1987     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1988     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1989     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1990     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1991     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1992     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1993     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1994     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1995     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1996     ierr = VecDestroy(&x);CHKERRQ(ierr);
1997     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1998   }
1999 
2000   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
2001   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2002   if (isseqaij) {
2003     Mat M;
2004 
2005     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2006     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
2007     ierr = MatDestroy(&M);CHKERRQ(ierr);
2008   } else {
2009     Mat work_mat,M;
2010 
2011     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2012     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
2013     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
2014     ierr = MatDestroy(&M);CHKERRQ(ierr);
2015     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2016   }
2017   if (matis->A->symmetric_set) {
2018     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2019 #if !defined(PETSC_USE_COMPLEX)
2020     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2021 #endif
2022   }
2023   /*
2024   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2025   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
2026   */
2027   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2028   PetscFunctionReturn(0);
2029 }
2030 
2031 #undef __FUNCT__
2032 #define __FUNCT__ "PCBDDCSetUpLocalScatters"
2033 PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2034 {
2035   PC_IS*          pcis = (PC_IS*)(pc->data);
2036   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2037   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2038   PetscInt        *idx_R_local=NULL;
2039   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
2040   PetscInt        vbs,bs;
2041   PetscBT         bitmask=NULL;
2042   PetscErrorCode  ierr;
2043 
2044   PetscFunctionBegin;
2045   /*
2046     No need to setup local scatters if
2047       - primal space is unchanged
2048         AND
2049       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2050         AND
2051       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2052   */
2053   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2054     PetscFunctionReturn(0);
2055   }
2056   /* destroy old objects */
2057   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2058   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2059   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2060   /* Set Non-overlapping dimensions */
2061   n_B = pcis->n_B;
2062   n_D = pcis->n - n_B;
2063   n_vertices = pcbddc->n_vertices;
2064 
2065   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
2066 
2067   /* create auxiliary bitmask and allocate workspace */
2068   if (!sub_schurs->reuse_mumps) {
2069     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2070     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2071     for (i=0;i<n_vertices;i++) {
2072       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2073     }
2074 
2075     for (i=0, n_R=0; i<pcis->n; i++) {
2076       if (!PetscBTLookup(bitmask,i)) {
2077         idx_R_local[n_R++] = i;
2078       }
2079     }
2080   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
2081     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2082 
2083     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2084     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
2085   }
2086 
2087   /* Block code */
2088   vbs = 1;
2089   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
2090   if (bs>1 && !(n_vertices%bs)) {
2091     PetscBool is_blocked = PETSC_TRUE;
2092     PetscInt  *vary;
2093     if (!sub_schurs->reuse_mumps) {
2094       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
2095       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2096       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2097       /* 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 */
2098       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2099       for (i=0; i<pcis->n/bs; i++) {
2100         if (vary[i]!=0 && vary[i]!=bs) {
2101           is_blocked = PETSC_FALSE;
2102           break;
2103         }
2104       }
2105       ierr = PetscFree(vary);CHKERRQ(ierr);
2106     } else {
2107       /* Verify directly the R set */
2108       for (i=0; i<n_R/bs; i++) {
2109         PetscInt j,node=idx_R_local[bs*i];
2110         for (j=1; j<bs; j++) {
2111           if (node != idx_R_local[bs*i+j]-j) {
2112             is_blocked = PETSC_FALSE;
2113             break;
2114           }
2115         }
2116       }
2117     }
2118     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
2119       vbs = bs;
2120       for (i=0;i<n_R/vbs;i++) {
2121         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
2122       }
2123     }
2124   }
2125   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2126   if (sub_schurs->reuse_mumps) {
2127     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2128 
2129     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2130     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
2131     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2132     reuse_mumps->is_R = pcbddc->is_R_local;
2133   } else {
2134     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
2135   }
2136 
2137   /* print some info if requested */
2138   if (pcbddc->dbg_flag) {
2139     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2140     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2141     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2142     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2143     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
2144     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);
2145     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2146   }
2147 
2148   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2149   if (!sub_schurs->reuse_mumps) {
2150     IS       is_aux1,is_aux2;
2151     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
2152 
2153     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2154     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2155     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2156     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2157     for (i=0; i<n_D; i++) {
2158       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
2159     }
2160     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2161     for (i=0, j=0; i<n_R; i++) {
2162       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
2163         aux_array1[j++] = i;
2164       }
2165     }
2166     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2167     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2168     for (i=0, j=0; i<n_B; i++) {
2169       if (!PetscBTLookup(bitmask,is_indices[i])) {
2170         aux_array2[j++] = i;
2171       }
2172     }
2173     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2174     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2175     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2176     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2177     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2178 
2179     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2180       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2181       for (i=0, j=0; i<n_R; i++) {
2182         if (PetscBTLookup(bitmask,idx_R_local[i])) {
2183           aux_array1[j++] = i;
2184         }
2185       }
2186       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2187       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2188       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2189     }
2190     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
2191     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2192   } else {
2193     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2194     IS               tis;
2195     PetscInt         schur_size;
2196 
2197     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
2198     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
2199     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
2200     ierr = ISDestroy(&tis);CHKERRQ(ierr);
2201     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2202       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
2203       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2204       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2205     }
2206   }
2207   PetscFunctionReturn(0);
2208 }
2209 
2210 
2211 #undef __FUNCT__
2212 #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2213 PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2214 {
2215   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2216   PC_IS          *pcis = (PC_IS*)pc->data;
2217   PC             pc_temp;
2218   Mat            A_RR;
2219   MatReuse       reuse;
2220   PetscScalar    m_one = -1.0;
2221   PetscReal      value;
2222   PetscInt       n_D,n_R;
2223   PetscBool      use_exact,use_exact_reduced,issbaij;
2224   PetscErrorCode ierr;
2225   /* prefixes stuff */
2226   char           dir_prefix[256],neu_prefix[256],str_level[16];
2227   size_t         len;
2228 
2229   PetscFunctionBegin;
2230 
2231   /* compute prefixes */
2232   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2233   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2234   if (!pcbddc->current_level) {
2235     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2236     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2237     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2238     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2239   } else {
2240     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2241     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2242     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2243     len -= 15; /* remove "pc_bddc_coarse_" */
2244     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2245     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
2246     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2247     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2248     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2249     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2250     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2251     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2252   }
2253 
2254   /* DIRICHLET PROBLEM */
2255   if (dirichlet) {
2256     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2257     if (pcbddc->local_mat->symmetric_set) {
2258       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2259     }
2260     /* Matrix for Dirichlet problem is pcis->A_II */
2261     n_D = pcis->n - pcis->n_B;
2262     if (!pcbddc->ksp_D) { /* create object if not yet build */
2263       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2264       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2265       /* default */
2266       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2267       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
2268       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2269       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2270       if (issbaij) {
2271         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
2272       } else {
2273         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
2274       }
2275       /* Allow user's customization */
2276       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2277       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2278     }
2279     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2280     if (sub_schurs->reuse_mumps) {
2281       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2282 
2283       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
2284     }
2285     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2286     if (!n_D) {
2287       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2288       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2289     }
2290     /* Set Up KSP for Dirichlet problem of BDDC */
2291     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2292     /* set ksp_D into pcis data */
2293     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2294     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2295     pcis->ksp_D = pcbddc->ksp_D;
2296   }
2297 
2298   /* NEUMANN PROBLEM */
2299   A_RR = 0;
2300   if (neumann) {
2301     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2302     PetscInt        ibs,mbs;
2303     PetscBool       issbaij;
2304     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2305     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
2306     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2307     if (pcbddc->ksp_R) { /* already created ksp */
2308       PetscInt nn_R;
2309       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2310       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2311       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2312       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2313         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2314         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2315         reuse = MAT_INITIAL_MATRIX;
2316       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2317         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2318           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2319           reuse = MAT_INITIAL_MATRIX;
2320         } else { /* safe to reuse the matrix */
2321           reuse = MAT_REUSE_MATRIX;
2322         }
2323       }
2324       /* last check */
2325       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2326         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2327         reuse = MAT_INITIAL_MATRIX;
2328       }
2329     } else { /* first time, so we need to create the matrix */
2330       reuse = MAT_INITIAL_MATRIX;
2331     }
2332     /* extract A_RR */
2333     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2334     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
2335     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2336     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
2337       if (matis->A == pcbddc->local_mat) {
2338         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2339         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2340       } else {
2341         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2342       }
2343     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
2344       if (matis->A == pcbddc->local_mat) {
2345         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2346         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2347       } else {
2348         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2349       }
2350     }
2351     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
2352     if (pcbddc->local_mat->symmetric_set) {
2353       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2354     }
2355     if (!pcbddc->ksp_R) { /* create object if not present */
2356       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2357       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2358       /* default */
2359       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2360       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2361       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2362       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2363       if (issbaij) {
2364         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
2365       } else {
2366         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
2367       }
2368       /* Allow user's customization */
2369       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2370       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2371     }
2372     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2373     if (!n_R) {
2374       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2375       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2376     }
2377     /* Reuse MUMPS solver if it is present */
2378     if (sub_schurs->reuse_mumps) {
2379       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2380 
2381       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2382     }
2383     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2384     /* Set Up KSP for Neumann problem of BDDC */
2385     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2386   }
2387   /* free Neumann problem's matrix */
2388   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2389 
2390   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
2391   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2392     if (pcbddc->dbg_flag) {
2393       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2394       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2395       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2396     }
2397     if (dirichlet) { /* Dirichlet */
2398       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
2399       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2400       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
2401       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
2402       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2403       /* need to be adapted? */
2404       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2405       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2406       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2407       /* print info */
2408       if (pcbddc->dbg_flag) {
2409         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);
2410         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2411       }
2412       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2413         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2414       }
2415     }
2416     if (neumann) { /* Neumann */
2417       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
2418       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
2419       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2420       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
2421       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
2422       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2423       /* need to be adapted? */
2424       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2425       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2426       /* print info */
2427       if (pcbddc->dbg_flag) {
2428         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);
2429         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2430       }
2431       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2432         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2433       }
2434     }
2435   }
2436   PetscFunctionReturn(0);
2437 }
2438 
2439 #undef __FUNCT__
2440 #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
2441 static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2442 {
2443   PetscErrorCode  ierr;
2444   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2445   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2446 
2447   PetscFunctionBegin;
2448   if (!sub_schurs->reuse_mumps) {
2449     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
2450   }
2451   if (!pcbddc->switch_static) {
2452     if (applytranspose && pcbddc->local_auxmat1) {
2453       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
2454       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
2455     }
2456     if (!sub_schurs->reuse_mumps) {
2457       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2458       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2459     } else {
2460       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2461 
2462       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2463       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2464     }
2465   } else {
2466     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2467     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2468     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2469     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2470     if (applytranspose && pcbddc->local_auxmat1) {
2471       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
2472       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
2473       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2474       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2475     }
2476   }
2477   if (!sub_schurs->reuse_mumps) {
2478     if (applytranspose) {
2479       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
2480     } else {
2481       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
2482     }
2483 #if defined(PETSC_HAVE_MUMPS)
2484   } else {
2485     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2486 
2487     if (applytranspose) {
2488       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2489     } else {
2490       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2491     }
2492 #endif
2493   }
2494   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
2495   if (!pcbddc->switch_static) {
2496     if (!sub_schurs->reuse_mumps) {
2497       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2498       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2499     } else {
2500       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2501 
2502       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2503       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2504     }
2505     if (!applytranspose && pcbddc->local_auxmat1) {
2506       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
2507       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
2508     }
2509   } else {
2510     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2511     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2512     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2513     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2514     if (!applytranspose && pcbddc->local_auxmat1) {
2515       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
2516       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
2517     }
2518     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2519     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2520     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2521     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2522   }
2523   PetscFunctionReturn(0);
2524 }
2525 
2526 /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2527 #undef __FUNCT__
2528 #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2529 PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2530 {
2531   PetscErrorCode ierr;
2532   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2533   PC_IS*            pcis = (PC_IS*)  (pc->data);
2534   const PetscScalar zero = 0.0;
2535 
2536   PetscFunctionBegin;
2537   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2538   if (applytranspose) {
2539     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2540     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2541   } else {
2542     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2543     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2544   }
2545 
2546   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
2547   if (pcbddc->benign_n) {
2548     PetscScalar *array;
2549     PetscInt    j;
2550 
2551     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2552     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2553     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2554   }
2555 
2556   /* start communications from local primal nodes to rhs of coarse solver */
2557   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
2558   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2559   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2560 
2561   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
2562   /* TODO remove null space when doing multilevel */
2563   if (pcbddc->coarse_ksp) {
2564     Mat coarse_mat;
2565     Vec rhs,sol;
2566     MatNullSpace nullsp;
2567 
2568     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2569     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
2570     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
2571     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
2572     if (nullsp) {
2573       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
2574     }
2575     if (applytranspose) {
2576       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
2577     } else {
2578       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
2579     }
2580     if (nullsp) {
2581       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
2582     }
2583   }
2584 
2585   /* Local solution on R nodes */
2586   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
2587     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
2588   }
2589 
2590   /* communications from coarse sol to local primal nodes */
2591   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2592   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2593 
2594   /* Sum contributions from two levels */
2595   if (applytranspose) {
2596     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2597     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2598   } else {
2599     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2600     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2601   }
2602   /* store p0 */
2603   if (pcbddc->benign_n) {
2604     PetscScalar *array;
2605     PetscInt    j;
2606 
2607     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2608     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
2609     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2610   }
2611   PetscFunctionReturn(0);
2612 }
2613 
2614 #undef __FUNCT__
2615 #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
2616 PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2617 {
2618   PetscErrorCode ierr;
2619   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
2620   PetscScalar    *array;
2621   Vec            from,to;
2622 
2623   PetscFunctionBegin;
2624   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
2625     from = pcbddc->coarse_vec;
2626     to = pcbddc->vec1_P;
2627     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
2628       Vec tvec;
2629 
2630       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
2631       ierr = VecResetArray(tvec);CHKERRQ(ierr);
2632       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
2633       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
2634       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
2635       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
2636     }
2637   } else { /* from local to global -> put data in coarse right hand side */
2638     from = pcbddc->vec1_P;
2639     to = pcbddc->coarse_vec;
2640   }
2641   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2642   PetscFunctionReturn(0);
2643 }
2644 
2645 #undef __FUNCT__
2646 #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
2647 PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2648 {
2649   PetscErrorCode ierr;
2650   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
2651   PetscScalar    *array;
2652   Vec            from,to;
2653 
2654   PetscFunctionBegin;
2655   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
2656     from = pcbddc->coarse_vec;
2657     to = pcbddc->vec1_P;
2658   } else { /* from local to global -> put data in coarse right hand side */
2659     from = pcbddc->vec1_P;
2660     to = pcbddc->coarse_vec;
2661   }
2662   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2663   if (smode == SCATTER_FORWARD) {
2664     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
2665       Vec tvec;
2666 
2667       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
2668       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
2669       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
2670       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
2671     }
2672   } else {
2673     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
2674      ierr = VecResetArray(from);CHKERRQ(ierr);
2675     }
2676   }
2677   PetscFunctionReturn(0);
2678 }
2679 
2680 /* uncomment for testing purposes */
2681 /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2682 #undef __FUNCT__
2683 #define __FUNCT__ "PCBDDCConstraintsSetUp"
2684 PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2685 {
2686   PetscErrorCode    ierr;
2687   PC_IS*            pcis = (PC_IS*)(pc->data);
2688   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2689   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2690   /* one and zero */
2691   PetscScalar       one=1.0,zero=0.0;
2692   /* space to store constraints and their local indices */
2693   PetscScalar       *constraints_data;
2694   PetscInt          *constraints_idxs,*constraints_idxs_B;
2695   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
2696   PetscInt          *constraints_n;
2697   /* iterators */
2698   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2699   /* BLAS integers */
2700   PetscBLASInt      lwork,lierr;
2701   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2702   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2703   /* reuse */
2704   PetscInt          olocal_primal_size,olocal_primal_size_cc;
2705   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2706   /* change of basis */
2707   PetscBool         qr_needed;
2708   PetscBT           change_basis,qr_needed_idx;
2709   /* auxiliary stuff */
2710   PetscInt          *nnz,*is_indices;
2711   PetscInt          ncc;
2712   /* some quantities */
2713   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2714   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2715 
2716   PetscFunctionBegin;
2717   /* Destroy Mat objects computed previously */
2718   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2719   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2720   /* save info on constraints from previous setup (if any) */
2721   olocal_primal_size = pcbddc->local_primal_size;
2722   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
2723   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
2724   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
2725   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
2726   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2727   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2728 
2729   /* print some info */
2730   if (pcbddc->dbg_flag) {
2731     IS       vertices;
2732     PetscInt nv,nedges,nfaces;
2733     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2734     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2735     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2736     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2737     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2738     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2739     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2740     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2741     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2742   }
2743 
2744   if (!pcbddc->adaptive_selection) {
2745     IS           ISForVertices,*ISForFaces,*ISForEdges;
2746     MatNullSpace nearnullsp;
2747     const Vec    *nearnullvecs;
2748     Vec          *localnearnullsp;
2749     PetscScalar  *array;
2750     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2751     PetscBool    nnsp_has_cnst;
2752     /* LAPACK working arrays for SVD or POD */
2753     PetscBool    skip_lapack,boolforchange;
2754     PetscScalar  *work;
2755     PetscReal    *singular_vals;
2756 #if defined(PETSC_USE_COMPLEX)
2757     PetscReal    *rwork;
2758 #endif
2759 #if defined(PETSC_MISSING_LAPACK_GESVD)
2760     PetscScalar  *temp_basis,*correlation_mat;
2761 #else
2762     PetscBLASInt dummy_int=1;
2763     PetscScalar  dummy_scalar=1.;
2764 #endif
2765 
2766     /* Get index sets for faces, edges and vertices from graph */
2767     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2768     /* free unneeded index sets */
2769     if (!pcbddc->use_vertices) {
2770       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2771     }
2772     if (!pcbddc->use_edges) {
2773       for (i=0;i<n_ISForEdges;i++) {
2774         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2775       }
2776       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2777       n_ISForEdges = 0;
2778     }
2779     if (!pcbddc->use_faces) {
2780       for (i=0;i<n_ISForFaces;i++) {
2781         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2782       }
2783       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2784       n_ISForFaces = 0;
2785     }
2786 
2787 #if defined(PETSC_USE_DEBUG)
2788     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
2789        Also use_change_of_basis should be consistent among processors */
2790     if (pcbddc->NullSpace) {
2791       PetscBool tbool[2],gbool[2];
2792 
2793       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2794         pcbddc->use_change_of_basis = PETSC_TRUE;
2795         if (!ISForEdges) {
2796           pcbddc->use_change_on_faces = PETSC_TRUE;
2797         }
2798       }
2799       tbool[0] = pcbddc->use_change_of_basis;
2800       tbool[1] = pcbddc->use_change_on_faces;
2801       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2802       pcbddc->use_change_of_basis = gbool[0];
2803       pcbddc->use_change_on_faces = gbool[1];
2804     }
2805 #endif
2806 
2807     /* check if near null space is attached to global mat */
2808     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2809     if (nearnullsp) {
2810       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2811       /* remove any stored info */
2812       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2813       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2814       /* store information for BDDC solver reuse */
2815       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2816       pcbddc->onearnullspace = nearnullsp;
2817       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2818       for (i=0;i<nnsp_size;i++) {
2819         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2820       }
2821     } else { /* if near null space is not provided BDDC uses constants by default */
2822       nnsp_size = 0;
2823       nnsp_has_cnst = PETSC_TRUE;
2824     }
2825     /* get max number of constraints on a single cc */
2826     max_constraints = nnsp_size;
2827     if (nnsp_has_cnst) max_constraints++;
2828 
2829     /*
2830          Evaluate maximum storage size needed by the procedure
2831          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
2832          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
2833          There can be multiple constraints per connected component
2834                                                                                                                                                            */
2835     n_vertices = 0;
2836     if (ISForVertices) {
2837       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2838     }
2839     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
2840     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
2841 
2842     total_counts = n_ISForFaces+n_ISForEdges;
2843     total_counts *= max_constraints;
2844     total_counts += n_vertices;
2845     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
2846 
2847     total_counts = 0;
2848     max_size_of_constraint = 0;
2849     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
2850       IS used_is;
2851       if (i<n_ISForEdges) {
2852         used_is = ISForEdges[i];
2853       } else {
2854         used_is = ISForFaces[i-n_ISForEdges];
2855       }
2856       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2857       total_counts += j;
2858       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2859     }
2860     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);
2861 
2862     /* get local part of global near null space vectors */
2863     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2864     for (k=0;k<nnsp_size;k++) {
2865       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2866       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2867       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2868     }
2869 
2870     /* whether or not to skip lapack calls */
2871     skip_lapack = PETSC_TRUE;
2872     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2873 
2874     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2875     if (!skip_lapack) {
2876       PetscScalar temp_work;
2877 
2878 #if defined(PETSC_MISSING_LAPACK_GESVD)
2879       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2880       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2881       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2882       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2883 #if defined(PETSC_USE_COMPLEX)
2884       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2885 #endif
2886       /* now we evaluate the optimal workspace using query with lwork=-1 */
2887       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2888       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2889       lwork = -1;
2890       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2891 #if !defined(PETSC_USE_COMPLEX)
2892       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2893 #else
2894       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2895 #endif
2896       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2897       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2898 #else /* on missing GESVD */
2899       /* SVD */
2900       PetscInt max_n,min_n;
2901       max_n = max_size_of_constraint;
2902       min_n = max_constraints;
2903       if (max_size_of_constraint < max_constraints) {
2904         min_n = max_size_of_constraint;
2905         max_n = max_constraints;
2906       }
2907       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2908 #if defined(PETSC_USE_COMPLEX)
2909       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2910 #endif
2911       /* now we evaluate the optimal workspace using query with lwork=-1 */
2912       lwork = -1;
2913       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2914       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2915       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2916       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2917 #if !defined(PETSC_USE_COMPLEX)
2918       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));
2919 #else
2920       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));
2921 #endif
2922       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2923       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2924 #endif /* on missing GESVD */
2925       /* Allocate optimal workspace */
2926       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2927       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2928     }
2929     /* Now we can loop on constraining sets */
2930     total_counts = 0;
2931     constraints_idxs_ptr[0] = 0;
2932     constraints_data_ptr[0] = 0;
2933     /* vertices */
2934     if (n_vertices) {
2935       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2936       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2937       for (i=0;i<n_vertices;i++) {
2938         constraints_n[total_counts] = 1;
2939         constraints_data[total_counts] = 1.0;
2940         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
2941         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2942         total_counts++;
2943       }
2944       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2945       n_vertices = total_counts;
2946     }
2947 
2948     /* edges and faces */
2949     total_counts_cc = total_counts;
2950     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
2951       IS        used_is;
2952       PetscBool idxs_copied = PETSC_FALSE;
2953 
2954       if (ncc<n_ISForEdges) {
2955         used_is = ISForEdges[ncc];
2956         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2957       } else {
2958         used_is = ISForFaces[ncc-n_ISForEdges];
2959         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2960       }
2961       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
2962 
2963       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
2964       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2965       /* change of basis should not be performed on local periodic nodes */
2966       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2967       if (nnsp_has_cnst) {
2968         PetscScalar quad_value;
2969 
2970         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
2971         idxs_copied = PETSC_TRUE;
2972 
2973         if (!pcbddc->use_nnsp_true) {
2974           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2975         } else {
2976           quad_value = 1.0;
2977         }
2978         for (j=0;j<size_of_constraint;j++) {
2979           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2980         }
2981         temp_constraints++;
2982         total_counts++;
2983       }
2984       for (k=0;k<nnsp_size;k++) {
2985         PetscReal real_value;
2986         PetscScalar *ptr_to_data;
2987 
2988         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2989         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2990         for (j=0;j<size_of_constraint;j++) {
2991           ptr_to_data[j] = array[is_indices[j]];
2992         }
2993         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2994         /* check if array is null on the connected component */
2995         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2996         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
2997         if (real_value > 0.0) { /* keep indices and values */
2998           temp_constraints++;
2999           total_counts++;
3000           if (!idxs_copied) {
3001             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
3002             idxs_copied = PETSC_TRUE;
3003           }
3004         }
3005       }
3006       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3007       valid_constraints = temp_constraints;
3008       if (!pcbddc->use_nnsp_true && temp_constraints) {
3009         if (temp_constraints == 1) { /* just normalize the constraint */
3010           PetscScalar norm,*ptr_to_data;
3011 
3012           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3013           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3014           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3015           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
3016           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3017         } else { /* perform SVD */
3018           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
3019           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3020 
3021 #if defined(PETSC_MISSING_LAPACK_GESVD)
3022           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3023              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3024              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3025                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3026                 from that computed using LAPACKgesvd
3027              -> This is due to a different computation of eigenvectors in LAPACKheev
3028              -> The quality of the POD-computed basis will be the same */
3029           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3030           /* Store upper triangular part of correlation matrix */
3031           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3032           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3033           for (j=0;j<temp_constraints;j++) {
3034             for (k=0;k<j+1;k++) {
3035               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));
3036             }
3037           }
3038           /* compute eigenvalues and eigenvectors of correlation matrix */
3039           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3040           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3041 #if !defined(PETSC_USE_COMPLEX)
3042           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3043 #else
3044           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3045 #endif
3046           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3047           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3048           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3049           j = 0;
3050           while (j < temp_constraints && singular_vals[j] < tol) j++;
3051           total_counts = total_counts-j;
3052           valid_constraints = temp_constraints-j;
3053           /* scale and copy POD basis into used quadrature memory */
3054           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3055           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3056           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3057           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3058           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3059           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3060           if (j<temp_constraints) {
3061             PetscInt ii;
3062             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3063             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3064             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));
3065             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3066             for (k=0;k<temp_constraints-j;k++) {
3067               for (ii=0;ii<size_of_constraint;ii++) {
3068                 ptr_to_data[k*size_of_constraint+ii] = singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii];
3069               }
3070             }
3071           }
3072 #else  /* on missing GESVD */
3073           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3074           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3075           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3076           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3077 #if !defined(PETSC_USE_COMPLEX)
3078           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));
3079 #else
3080           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));
3081 #endif
3082           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3083           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3084           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3085           k = temp_constraints;
3086           if (k > size_of_constraint) k = size_of_constraint;
3087           j = 0;
3088           while (j < k && singular_vals[k-j-1] < tol) j++;
3089           valid_constraints = k-j;
3090           total_counts = total_counts-temp_constraints+valid_constraints;
3091 #endif /* on missing GESVD */
3092         }
3093       }
3094       /* update pointers information */
3095       if (valid_constraints) {
3096         constraints_n[total_counts_cc] = valid_constraints;
3097         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
3098         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
3099         /* set change_of_basis flag */
3100         if (boolforchange) {
3101           PetscBTSet(change_basis,total_counts_cc);
3102         }
3103         total_counts_cc++;
3104       }
3105     }
3106     /* free workspace */
3107     if (!skip_lapack) {
3108       ierr = PetscFree(work);CHKERRQ(ierr);
3109 #if defined(PETSC_USE_COMPLEX)
3110       ierr = PetscFree(rwork);CHKERRQ(ierr);
3111 #endif
3112       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3113 #if defined(PETSC_MISSING_LAPACK_GESVD)
3114       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3115       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3116 #endif
3117     }
3118     for (k=0;k<nnsp_size;k++) {
3119       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3120     }
3121     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3122     /* free index sets of faces, edges and vertices */
3123     for (i=0;i<n_ISForFaces;i++) {
3124       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3125     }
3126     if (n_ISForFaces) {
3127       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3128     }
3129     for (i=0;i<n_ISForEdges;i++) {
3130       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3131     }
3132     if (n_ISForEdges) {
3133       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3134     }
3135     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3136   } else {
3137     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3138 
3139     total_counts = 0;
3140     n_vertices = 0;
3141     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3142       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
3143     }
3144     max_constraints = 0;
3145     total_counts_cc = 0;
3146     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
3147       total_counts += pcbddc->adaptive_constraints_n[i];
3148       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
3149       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
3150     }
3151     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
3152     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
3153     constraints_idxs = pcbddc->adaptive_constraints_idxs;
3154     constraints_data = pcbddc->adaptive_constraints_data;
3155     /* constraints_n differs from pcbddc->adaptive_constraints_n */
3156     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
3157     total_counts_cc = 0;
3158     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
3159       if (pcbddc->adaptive_constraints_n[i]) {
3160         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
3161       }
3162     }
3163 #if 0
3164     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
3165     for (i=0;i<total_counts_cc;i++) {
3166       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
3167       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
3168       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
3169         printf(" %d",constraints_idxs[j]);
3170       }
3171       printf("\n");
3172       printf("number of cc: %d\n",constraints_n[i]);
3173     }
3174     for (i=0;i<n_vertices;i++) {
3175       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
3176     }
3177     for (i=0;i<sub_schurs->n_subs;i++) {
3178       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]);
3179     }
3180 #endif
3181 
3182     max_size_of_constraint = 0;
3183     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]);
3184     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
3185     /* Change of basis */
3186     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
3187     if (pcbddc->use_change_of_basis) {
3188       for (i=0;i<sub_schurs->n_subs;i++) {
3189         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3190           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
3191         }
3192       }
3193     }
3194   }
3195   pcbddc->local_primal_size = total_counts;
3196   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3197 
3198   /* map constraints_idxs in boundary numbering */
3199   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
3200   if (i != constraints_idxs_ptr[total_counts_cc]) {
3201     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",constraints_idxs_ptr[total_counts_cc],i);
3202   }
3203 
3204   /* Create constraint matrix */
3205   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
3206   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3207   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3208 
3209   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3210   /* determine if a QR strategy is needed for change of basis */
3211   qr_needed = PETSC_FALSE;
3212   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3213   total_primal_vertices=0;
3214   pcbddc->local_primal_size_cc = 0;
3215   for (i=0;i<total_counts_cc;i++) {
3216     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3217     if (size_of_constraint == 1) {
3218       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3219       pcbddc->local_primal_size_cc += 1;
3220     } else if (PetscBTLookup(change_basis,i)) {
3221       for (k=0;k<constraints_n[i];k++) {
3222         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3223       }
3224       pcbddc->local_primal_size_cc += constraints_n[i];
3225       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3226         PetscBTSet(qr_needed_idx,i);
3227         qr_needed = PETSC_TRUE;
3228       }
3229     } else {
3230       pcbddc->local_primal_size_cc += 1;
3231     }
3232   }
3233   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3234   pcbddc->n_vertices = total_primal_vertices;
3235   /* permute indices in order to have a sorted set of vertices */
3236   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3237 
3238   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);
3239   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3240   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3241 
3242   /* nonzero structure of constraint matrix */
3243   /* and get reference dof for local constraints */
3244   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3245   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
3246 
3247   j = total_primal_vertices;
3248   total_counts = total_primal_vertices;
3249   cum = total_primal_vertices;
3250   for (i=n_vertices;i<total_counts_cc;i++) {
3251     if (!PetscBTLookup(change_basis,i)) {
3252       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3253       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3254       cum++;
3255       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3256       for (k=0;k<constraints_n[i];k++) {
3257         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3258         nnz[j+k] = size_of_constraint;
3259       }
3260       j += constraints_n[i];
3261     }
3262   }
3263   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3264   ierr = PetscFree(nnz);CHKERRQ(ierr);
3265 
3266   /* set values in constraint matrix */
3267   for (i=0;i<total_primal_vertices;i++) {
3268     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3269   }
3270   total_counts = total_primal_vertices;
3271   for (i=n_vertices;i<total_counts_cc;i++) {
3272     if (!PetscBTLookup(change_basis,i)) {
3273       PetscInt *cols;
3274 
3275       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3276       cols = constraints_idxs+constraints_idxs_ptr[i];
3277       for (k=0;k<constraints_n[i];k++) {
3278         PetscInt    row = total_counts+k;
3279         PetscScalar *vals;
3280 
3281         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
3282         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
3283       }
3284       total_counts += constraints_n[i];
3285     }
3286   }
3287   /* assembling */
3288   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3289   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3290 
3291   /*
3292   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3293   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3294   */
3295   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3296   if (pcbddc->use_change_of_basis) {
3297     /* dual and primal dofs on a single cc */
3298     PetscInt     dual_dofs,primal_dofs;
3299     /* working stuff for GEQRF */
3300     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3301     PetscBLASInt lqr_work;
3302     /* working stuff for UNGQR */
3303     PetscScalar  *gqr_work,lgqr_work_t;
3304     PetscBLASInt lgqr_work;
3305     /* working stuff for TRTRS */
3306     PetscScalar  *trs_rhs;
3307     PetscBLASInt Blas_NRHS;
3308     /* pointers for values insertion into change of basis matrix */
3309     PetscInt     *start_rows,*start_cols;
3310     PetscScalar  *start_vals;
3311     /* working stuff for values insertion */
3312     PetscBT      is_primal;
3313     PetscInt     *aux_primal_numbering_B;
3314     /* matrix sizes */
3315     PetscInt     global_size,local_size;
3316     /* temporary change of basis */
3317     Mat          localChangeOfBasisMatrix;
3318     /* extra space for debugging */
3319     PetscScalar  *dbg_work;
3320 
3321     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3322     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
3323     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3324     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3325     /* nonzeros for local mat */
3326     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3327     for (i=0;i<pcis->n;i++) nnz[i]=1;
3328     for (i=n_vertices;i<total_counts_cc;i++) {
3329       if (PetscBTLookup(change_basis,i)) {
3330         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3331         if (PetscBTLookup(qr_needed_idx,i)) {
3332           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3333         } else {
3334           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
3335           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3336         }
3337       }
3338     }
3339     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3340     ierr = PetscFree(nnz);CHKERRQ(ierr);
3341     /* Set initial identity in the matrix */
3342     for (i=0;i<pcis->n;i++) {
3343       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3344     }
3345 
3346     if (pcbddc->dbg_flag) {
3347       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3348       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3349     }
3350 
3351 
3352     /* Now we loop on the constraints which need a change of basis */
3353     /*
3354        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3355        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3356 
3357        Basic blocks of change of basis matrix T computed by
3358 
3359           - Using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified)
3360 
3361             | 1        0   ...        0         s_1/S |
3362             | 0        1   ...        0         s_2/S |
3363             |              ...                        |
3364             | 0        ...            1     s_{n-1}/S |
3365             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3366 
3367             with S = \sum_{i=1}^n s_i^2
3368             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3369                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3370 
3371           - QR decomposition of constraints otherwise
3372     */
3373     if (qr_needed) {
3374       /* space to store Q */
3375       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3376       /* first we issue queries for optimal work */
3377       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
3378       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3379       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3380       lqr_work = -1;
3381       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3382       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3383       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3384       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3385       lgqr_work = -1;
3386       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
3387       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
3388       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
3389       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3390       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
3391       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3392       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3393       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3394       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3395       /* array to store scaling factors for reflectors */
3396       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3397       /* array to store rhs and solution of triangular solver */
3398       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3399       /* allocating workspace for check */
3400       if (pcbddc->dbg_flag) {
3401         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3402       }
3403     }
3404     /* array to store whether a node is primal or not */
3405     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3406     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
3407     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
3408     if (i != total_primal_vertices) {
3409       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
3410     }
3411     for (i=0;i<total_primal_vertices;i++) {
3412       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
3413     }
3414     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3415 
3416     /* loop on constraints and see whether or not they need a change of basis and compute it */
3417     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
3418       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
3419       if (PetscBTLookup(change_basis,total_counts)) {
3420         /* get constraint info */
3421         primal_dofs = constraints_n[total_counts];
3422         dual_dofs = size_of_constraint-primal_dofs;
3423 
3424         if (pcbddc->dbg_flag) {
3425           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);
3426         }
3427 
3428         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3429 
3430           /* copy quadrature constraints for change of basis check */
3431           if (pcbddc->dbg_flag) {
3432             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3433           }
3434           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
3435           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3436 
3437           /* compute QR decomposition of constraints */
3438           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3439           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
3440           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3441           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3442           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3443           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3444           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3445 
3446           /* explictly compute R^-T */
3447           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3448           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
3449           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
3450           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
3451           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3452           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3453           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3454           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3455           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3456           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3457 
3458           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
3459           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3460           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3461           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
3462           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3463           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3464           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3465           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3466           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3467 
3468           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3469              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3470              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
3471           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3472           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
3473           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
3474           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3475           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3476           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3477           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3478           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));
3479           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3480           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3481 
3482           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
3483           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3484           /* insert cols for primal dofs */
3485           for (j=0;j<primal_dofs;j++) {
3486             start_vals = &qr_basis[j*size_of_constraint];
3487             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3488             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3489           }
3490           /* insert cols for dual dofs */
3491           for (j=0,k=0;j<dual_dofs;k++) {
3492             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3493               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
3494               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3495               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3496               j++;
3497             }
3498           }
3499 
3500           /* check change of basis */
3501           if (pcbddc->dbg_flag) {
3502             PetscInt   ii,jj;
3503             PetscBool valid_qr=PETSC_TRUE;
3504             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3505             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3506             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3507             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3508             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3509             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3510             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3511             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));
3512             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3513             for (jj=0;jj<size_of_constraint;jj++) {
3514               for (ii=0;ii<primal_dofs;ii++) {
3515                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3516                 if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
3517               }
3518             }
3519             if (!valid_qr) {
3520               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3521               for (jj=0;jj<size_of_constraint;jj++) {
3522                 for (ii=0;ii<primal_dofs;ii++) {
3523                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3524                     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]));
3525                   }
3526                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3527                     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]));
3528                   }
3529                 }
3530               }
3531             } else {
3532               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3533             }
3534           }
3535         } else { /* simple transformation block */
3536           PetscInt    row,col;
3537           PetscScalar val,norm;
3538 
3539           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3540           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,constraints_data+constraints_data_ptr[total_counts],&Blas_one,constraints_data+constraints_data_ptr[total_counts],&Blas_one));
3541           for (j=0;j<size_of_constraint;j++) {
3542             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
3543             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3544             if (!PetscBTLookup(is_primal,row_B)) {
3545               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3546               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
3547               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3548             } else {
3549               for (k=0;k<size_of_constraint;k++) {
3550                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3551                 if (row != col) {
3552                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3553                 } else {
3554                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3555                 }
3556                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3557               }
3558             }
3559           }
3560           if (pcbddc->dbg_flag) {
3561             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3562           }
3563         }
3564       } else {
3565         if (pcbddc->dbg_flag) {
3566           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,size_of_constraint);CHKERRQ(ierr);
3567         }
3568       }
3569     }
3570 
3571     /* free workspace */
3572     if (qr_needed) {
3573       if (pcbddc->dbg_flag) {
3574         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3575       }
3576       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3577       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3578       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3579       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3580       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3581     }
3582     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3583     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3584     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3585 
3586     /* assembling of global change of variable */
3587     {
3588       Mat      tmat;
3589       PetscInt bs;
3590 
3591       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3592       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3593       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3594       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3595       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3596       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3597       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
3598       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3599       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3600       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3601       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3602       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3603       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3604       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3605       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3606       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3607       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3608       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3609     }
3610     /* check */
3611     if (pcbddc->dbg_flag) {
3612       PetscReal error;
3613       Vec       x,x_change;
3614 
3615       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3616       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3617       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3618       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3619       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3620       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3621       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3622       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3623       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3624       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3625       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3626       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3627       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3628       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3629       ierr = VecDestroy(&x);CHKERRQ(ierr);
3630       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3631     }
3632 
3633     /* adapt sub_schurs computed (if any) */
3634     if (pcbddc->use_deluxe_scaling) {
3635       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3636       if (sub_schurs->S_Ej_all) {
3637         Mat                    S_new,tmat;
3638         ISLocalToGlobalMapping NtoSall;
3639         IS                     is_all_N,is_V,is_V_Sall;
3640         const PetscScalar      *array;
3641         const PetscInt         *idxs_V,*idxs_all;
3642         PetscInt               i,n_V;
3643 
3644         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
3645         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3646         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3647         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3648         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3649         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3650         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3651         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3652         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3653         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3654         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3655         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3656         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3657         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3658         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3659         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3660         for (i=0;i<n_V;i++) {
3661           PetscScalar val;
3662           PetscInt    idx;
3663 
3664           idx = idxs_V[i];
3665           val = array[idxs_all[idxs_V[i]]];
3666           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3667         }
3668         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3669         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3670         sub_schurs->S_Ej_all = S_new;
3671         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3672         if (sub_schurs->sum_S_Ej_all) {
3673           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3674           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3675           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3676           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3677           sub_schurs->sum_S_Ej_all = S_new;
3678           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3679         }
3680         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3681         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3682         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3683         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3684         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3685       }
3686     }
3687     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3688   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3689     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3690     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3691   }
3692 
3693   /* set up change of basis context */
3694   if (pcbddc->ChangeOfBasisMatrix) {
3695     PCBDDCChange_ctx change_ctx;
3696 
3697     if (!pcbddc->new_global_mat) {
3698       PetscInt global_size,local_size;
3699 
3700       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3701       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3702       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3703       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3704       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3705       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3706       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3707       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3708       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3709     } else {
3710       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3711       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3712       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3713     }
3714     if (!pcbddc->user_ChangeOfBasisMatrix) {
3715       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3716       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3717     } else {
3718       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3719       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3720     }
3721     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3722     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3723     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3724     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3725   }
3726 
3727   /* add pressure dofs to set of primal nodes for numbering purposes */
3728   for (i=0;i<pcbddc->benign_n;i++) {
3729     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
3730     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
3731     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3732     pcbddc->local_primal_size_cc++;
3733     pcbddc->local_primal_size++;
3734   }
3735 
3736   /* check if a new primal space has been introduced (also take into account benign trick) */
3737   pcbddc->new_primal_space_local = PETSC_TRUE;
3738   if (olocal_primal_size == pcbddc->local_primal_size) {
3739     ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3740     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3741     if (!pcbddc->new_primal_space_local) {
3742       ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3743       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3744     }
3745   }
3746   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3747   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3748   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3749 
3750   /* flush dbg viewer */
3751   if (pcbddc->dbg_flag) {
3752     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3753   }
3754 
3755   /* free workspace */
3756   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
3757   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
3758   if (!pcbddc->adaptive_selection) {
3759     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
3760     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
3761   } else {
3762     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
3763                       pcbddc->adaptive_constraints_idxs_ptr,
3764                       pcbddc->adaptive_constraints_data_ptr,
3765                       pcbddc->adaptive_constraints_idxs,
3766                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
3767     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
3768     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
3769   }
3770   PetscFunctionReturn(0);
3771 }
3772 
3773 #undef __FUNCT__
3774 #define __FUNCT__ "PCBDDCAnalyzeInterface"
3775 PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3776 {
3777   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3778   PC_IS       *pcis = (PC_IS*)pc->data;
3779   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
3780   PetscInt    ierr,i,vertex_size,N;
3781   PetscViewer viewer=pcbddc->dbg_viewer;
3782 
3783   PetscFunctionBegin;
3784   /* Reset previously computed graph */
3785   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3786   /* Init local Graph struct */
3787   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
3788   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3789 
3790   /* Check validity of the csr graph passed in by the user */
3791   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
3792     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);
3793   }
3794 
3795   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
3796   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
3797     PetscInt  *xadj,*adjncy;
3798     PetscInt  nvtxs;
3799     PetscBool flg_row=PETSC_FALSE;
3800 
3801     if (pcbddc->use_local_adj) {
3802 
3803       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3804       if (flg_row) {
3805         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3806         pcbddc->computed_rowadj = PETSC_TRUE;
3807       }
3808       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3809     } else if (pcbddc->current_level && pcis->n_B) { /* just compute subdomain's connected components for coarser levels when the local boundary is not empty */
3810       IS                     is_dummy;
3811       ISLocalToGlobalMapping l2gmap_dummy;
3812       PetscInt               j,sum;
3813       PetscInt               *cxadj,*cadjncy;
3814       const PetscInt         *idxs;
3815       PCBDDCGraph            graph;
3816       PetscBT                is_on_boundary;
3817 
3818       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
3819       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
3820       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
3821       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
3822       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
3823       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3824       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3825       if (flg_row) {
3826         graph->xadj = xadj;
3827         graph->adjncy = adjncy;
3828       }
3829       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
3830       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3831       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3832 
3833       if (pcbddc->dbg_flag) {
3834         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
3835         for (i=0;i<graph->ncc;i++) {
3836           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
3837         }
3838       }
3839 
3840       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
3841       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
3842       for (i=0;i<pcis->n_B;i++) {
3843         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
3844       }
3845       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
3846 
3847       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
3848       sum = 0;
3849       for (i=0;i<graph->ncc;i++) {
3850         PetscInt sizecc = 0;
3851         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
3852           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
3853             sizecc++;
3854           }
3855         }
3856         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
3857           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
3858             cxadj[graph->queue[j]] = sizecc;
3859           }
3860         }
3861         sum += sizecc*sizecc;
3862       }
3863       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
3864       sum = 0;
3865       for (i=0;i<pcis->n;i++) {
3866         PetscInt temp = cxadj[i];
3867         cxadj[i] = sum;
3868         sum += temp;
3869       }
3870       cxadj[pcis->n] = sum;
3871       for (i=0;i<graph->ncc;i++) {
3872         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
3873           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
3874             PetscInt k,sizecc = 0;
3875             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
3876               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
3877                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
3878                 sizecc++;
3879               }
3880             }
3881           }
3882         }
3883       }
3884       if (sum) {
3885         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
3886       } else {
3887         ierr = PetscFree(cxadj);CHKERRQ(ierr);
3888         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
3889       }
3890       graph->xadj = 0;
3891       graph->adjncy = 0;
3892       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
3893       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
3894     }
3895   }
3896   if (pcbddc->dbg_flag) {
3897     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3898   }
3899 
3900   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3901   vertex_size = 1;
3902   if (pcbddc->user_provided_isfordofs) {
3903     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
3904       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
3905       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3906         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
3907         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3908       }
3909       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
3910       pcbddc->n_ISForDofs = 0;
3911       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3912     }
3913     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3914     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
3915   } else {
3916     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
3917       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3918       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
3919       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
3920         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
3921       }
3922     }
3923   }
3924 
3925   /* Setup of Graph */
3926   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3927     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3928   }
3929   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3930     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3931   }
3932   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
3933     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3934   }
3935   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3936 
3937   /* attach info on disconnected subdomains if present */
3938   if (pcbddc->n_local_subs) {
3939     PetscInt *local_subs;
3940 
3941     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
3942     for (i=0;i<pcbddc->n_local_subs;i++) {
3943       const PetscInt *idxs;
3944       PetscInt       nl,j;
3945 
3946       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
3947       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
3948       for (j=0;j<nl;j++) {
3949         local_subs[idxs[j]] = i;
3950       }
3951       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
3952     }
3953     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
3954     pcbddc->mat_graph->local_subs = local_subs;
3955   }
3956 
3957   /* Graph's connected components analysis */
3958   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3959 
3960   /* print some info to stdout */
3961   if (pcbddc->dbg_flag) {
3962     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3963   }
3964 
3965   /* mark topography has done */
3966   pcbddc->recompute_topography = PETSC_FALSE;
3967   PetscFunctionReturn(0);
3968 }
3969 
3970 /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3971 #undef __FUNCT__
3972 #define __FUNCT__ "PCBDDCSubsetNumbering"
3973 PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3974 {
3975   PetscSF        sf;
3976   PetscLayout    map;
3977   const PetscInt *idxs;
3978   PetscInt       *leaf_data,*root_data,*gidxs;
3979   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3980   PetscInt       n_n,nlocals,start,first_index;
3981   PetscMPIInt    commsize;
3982   PetscBool      first_found;
3983   PetscErrorCode ierr;
3984 
3985   PetscFunctionBegin;
3986   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3987   if (subset_mult) {
3988     PetscCheckSameComm(subset,1,subset_mult,2);
3989     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3990     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3991   }
3992   /* create workspace layout for computing global indices of subset */
3993   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3994   lbounds[0] = lbounds[1] = 0;
3995   for (i=0;i<n;i++) {
3996     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3997     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3998   }
3999   lbounds[0] = -lbounds[0];
4000   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4001   gbounds[0] = -gbounds[0];
4002   N = gbounds[1] - gbounds[0] + 1;
4003   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4004   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4005   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4006   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4007   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4008 
4009   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4010   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4011   if (subset_mult) {
4012     const PetscInt* idxs_mult;
4013 
4014     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4015     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4016     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4017   } else {
4018     for (i=0;i<n;i++) leaf_data[i] = 1;
4019   }
4020   /* local size of new subset */
4021   n_n = 0;
4022   for (i=0;i<n;i++) n_n += leaf_data[i];
4023 
4024   /* global indexes in layout */
4025   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4026   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4027   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4028   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4029   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4030   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4031 
4032   /* reduce from leaves to roots */
4033   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
4034   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4035   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4036 
4037   /* count indexes in local part of layout */
4038   nlocals = 0;
4039   first_index = -1;
4040   first_found = PETSC_FALSE;
4041   for (i=0;i<Nl;i++) {
4042     if (!first_found && root_data[i]) {
4043       first_found = PETSC_TRUE;
4044       first_index = i;
4045     }
4046     nlocals += root_data[i];
4047   }
4048 
4049   /* cumulative of number of indexes and size of subset without holes */
4050 #if defined(PETSC_HAVE_MPI_EXSCAN)
4051   start = 0;
4052   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4053 #else
4054   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4055   start = start-nlocals;
4056 #endif
4057 
4058   if (N_n) { /* compute total size of new subset if requested */
4059     *N_n = start + nlocals;
4060     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4061     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4062   }
4063 
4064   /* adapt root data with cumulative */
4065   if (first_found) {
4066     PetscInt old_index;
4067 
4068     root_data[first_index] += start;
4069     old_index = first_index;
4070     for (i=first_index+1;i<Nl;i++) {
4071       if (root_data[i]) {
4072         root_data[i] += root_data[old_index];
4073         old_index = i;
4074       }
4075     }
4076   }
4077 
4078   /* from roots to leaves */
4079   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4080   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4081   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4082 
4083   /* create new IS with global indexes without holes */
4084   if (subset_mult) {
4085     const PetscInt* idxs_mult;
4086     PetscInt        cum;
4087 
4088     cum = 0;
4089     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4090     for (i=0;i<n;i++) {
4091       PetscInt j;
4092       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4093     }
4094     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4095   } else {
4096     for (i=0;i<n;i++) {
4097       gidxs[i] = leaf_data[i]-1;
4098     }
4099   }
4100   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4101   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4102   PetscFunctionReturn(0);
4103 }
4104 
4105 #undef __FUNCT__
4106 #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
4107 PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
4108 {
4109   PetscInt       i,j;
4110   PetscScalar    *alphas;
4111   PetscErrorCode ierr;
4112 
4113   PetscFunctionBegin;
4114   /* this implements stabilized Gram-Schmidt */
4115   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
4116   for (i=0;i<n;i++) {
4117     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
4118     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
4119     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
4120   }
4121   ierr = PetscFree(alphas);CHKERRQ(ierr);
4122   PetscFunctionReturn(0);
4123 }
4124 
4125 #undef __FUNCT__
4126 #define __FUNCT__ "MatISGetSubassemblingPattern"
4127 PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4128 {
4129   IS             ranks_send_to;
4130   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4131   PetscMPIInt    size,rank,color;
4132   PetscInt       *xadj,*adjncy;
4133   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
4134   PetscInt       i,local_size,threshold=0;
4135   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4136   PetscSubcomm   subcomm;
4137   PetscErrorCode ierr;
4138 
4139   PetscFunctionBegin;
4140   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
4141   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4142   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4143 
4144   /* Get info on mapping */
4145   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
4146   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4147 
4148   /* build local CSR graph of subdomains' connectivity */
4149   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4150   xadj[0] = 0;
4151   xadj[1] = PetscMax(n_neighs-1,0);
4152   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4153   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4154 
4155   if (threshold) {
4156     PetscInt xadj_count = 0;
4157     for (i=1;i<n_neighs;i++) {
4158       if (n_shared[i] > threshold) {
4159         adjncy[xadj_count] = neighs[i];
4160         adjncy_wgt[xadj_count] = n_shared[i];
4161         xadj_count++;
4162       }
4163     }
4164     xadj[1] = xadj_count;
4165   } else {
4166     if (xadj[1]) {
4167       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4168       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4169     }
4170   }
4171   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4172   if (use_square) {
4173     for (i=0;i<xadj[1];i++) {
4174       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4175     }
4176   }
4177   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4178 
4179   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4180 
4181   /*
4182     Restrict work on active processes only.
4183   */
4184   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4185   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4186   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
4187   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4188   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4189   if (color) {
4190     ierr = PetscFree(xadj);CHKERRQ(ierr);
4191     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4192     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4193   } else {
4194     Mat             subdomain_adj;
4195     IS              new_ranks,new_ranks_contig;
4196     MatPartitioning partitioner;
4197     PetscInt        prank,rstart=0,rend=0;
4198     PetscInt        *is_indices,*oldranks;
4199     PetscBool       aggregate;
4200 
4201     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4202     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4203     prank = rank;
4204     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
4205     /*
4206     for (i=0;i<size;i++) {
4207       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4208     }
4209     */
4210     for (i=0;i<xadj[1];i++) {
4211       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4212     }
4213     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4214     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4215     if (aggregate) {
4216       PetscInt    lrows,row,ncols,*cols;
4217       PetscMPIInt nrank;
4218       PetscScalar *vals;
4219 
4220       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4221       lrows = 0;
4222       if (nrank<redprocs) {
4223         lrows = size/redprocs;
4224         if (nrank<size%redprocs) lrows++;
4225       }
4226       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4227       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4228       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4229       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4230       row = nrank;
4231       ncols = xadj[1]-xadj[0];
4232       cols = adjncy;
4233       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4234       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4235       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4236       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4237       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4238       ierr = PetscFree(xadj);CHKERRQ(ierr);
4239       ierr = PetscFree(adjncy);CHKERRQ(ierr);
4240       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4241       ierr = PetscFree(vals);CHKERRQ(ierr);
4242     } else {
4243       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4244     }
4245     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4246 
4247     /* Partition */
4248     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4249     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4250     if (use_vwgt) {
4251       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4252       v_wgt[0] = local_size;
4253       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4254     }
4255     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
4256     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4257     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4258     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
4259     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4260 
4261     /* renumber new_ranks to avoid "holes" in new set of processors */
4262     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
4263     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
4264     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4265     if (!redprocs) {
4266       ranks_send_to_idx[0] = oldranks[is_indices[0]];
4267     } else {
4268       PetscInt    idxs[1];
4269       PetscMPIInt tag;
4270       MPI_Request *reqs;
4271 
4272       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4273       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4274       for (i=rstart;i<rend;i++) {
4275         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
4276       }
4277       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4278       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4279       ierr = PetscFree(reqs);CHKERRQ(ierr);
4280       ranks_send_to_idx[0] = oldranks[idxs[0]];
4281     }
4282     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4283     /* clean up */
4284     ierr = PetscFree(oldranks);CHKERRQ(ierr);
4285     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4286     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4287     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4288   }
4289   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4290 
4291   /* assemble parallel IS for sends */
4292   i = 1;
4293   if (color) i=0;
4294   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4295   /* get back IS */
4296   *is_sends = ranks_send_to;
4297   PetscFunctionReturn(0);
4298 }
4299 
4300 typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4301 
4302 #undef __FUNCT__
4303 #define __FUNCT__ "MatISSubassemble"
4304 PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
4305 {
4306   Mat                    local_mat;
4307   IS                     is_sends_internal;
4308   PetscInt               rows,cols,new_local_rows;
4309   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
4310   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4311   ISLocalToGlobalMapping l2gmap;
4312   PetscInt*              l2gmap_indices;
4313   const PetscInt*        is_indices;
4314   MatType                new_local_type;
4315   /* buffers */
4316   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
4317   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
4318   PetscInt               *recv_buffer_idxs_local;
4319   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4320   /* MPI */
4321   MPI_Comm               comm,comm_n;
4322   PetscSubcomm           subcomm;
4323   PetscMPIInt            n_sends,n_recvs,commsize;
4324   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
4325   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
4326   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
4327   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
4328   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4329   PetscErrorCode         ierr;
4330 
4331   PetscFunctionBegin;
4332   /* TODO: add missing checks */
4333   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
4334   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
4335   PetscValidLogicalCollectiveEnum(mat,reuse,5);
4336   PetscValidLogicalCollectiveInt(mat,nis,7);
4337   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
4338   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4339   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4340   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4341   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4342   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4343   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
4344   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
4345     PetscInt mrows,mcols,mnrows,mncols;
4346     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
4347     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
4348     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
4349     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
4350     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
4351     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
4352   }
4353   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4354   PetscValidLogicalCollectiveInt(mat,bs,0);
4355   /* prepare IS for sending if not provided */
4356   if (!is_sends) {
4357     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4358     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4359   } else {
4360     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4361     is_sends_internal = is_sends;
4362   }
4363 
4364   /* get comm */
4365   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4366 
4367   /* compute number of sends */
4368   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4369   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4370 
4371   /* compute number of receives */
4372   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4373   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4374   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4375   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4376   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4377   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4378   ierr = PetscFree(iflags);CHKERRQ(ierr);
4379 
4380   /* restrict comm if requested */
4381   subcomm = 0;
4382   destroy_mat = PETSC_FALSE;
4383   if (restrict_comm) {
4384     PetscMPIInt color,subcommsize;
4385 
4386     color = 0;
4387     if (restrict_full) {
4388       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
4389     } else {
4390       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
4391     }
4392     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
4393     subcommsize = commsize - subcommsize;
4394     /* check if reuse has been requested */
4395     if (reuse == MAT_REUSE_MATRIX) {
4396       if (*mat_n) {
4397         PetscMPIInt subcommsize2;
4398         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
4399         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
4400         comm_n = PetscObjectComm((PetscObject)*mat_n);
4401       } else {
4402         comm_n = PETSC_COMM_SELF;
4403       }
4404     } else { /* MAT_INITIAL_MATRIX */
4405       PetscMPIInt rank;
4406 
4407       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
4408       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
4409       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
4410       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4411       comm_n = PetscSubcommChild(subcomm);
4412     }
4413     /* flag to destroy *mat_n if not significative */
4414     if (color) destroy_mat = PETSC_TRUE;
4415   } else {
4416     comm_n = comm;
4417   }
4418 
4419   /* prepare send/receive buffers */
4420   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4421   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4422   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4423   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
4424   if (nis) {
4425     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
4426   }
4427 
4428   /* Get data from local matrices */
4429   if (!isdense) {
4430     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4431     /* TODO: See below some guidelines on how to prepare the local buffers */
4432     /*
4433        send_buffer_vals should contain the raw values of the local matrix
4434        send_buffer_idxs should contain:
4435        - MatType_PRIVATE type
4436        - PetscInt        size_of_l2gmap
4437        - PetscInt        global_row_indices[size_of_l2gmap]
4438        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4439     */
4440   } else {
4441     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4442     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4443     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4444     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4445     send_buffer_idxs[1] = i;
4446     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4447     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
4448     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4449     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4450     for (i=0;i<n_sends;i++) {
4451       ilengths_vals[is_indices[i]] = len*len;
4452       ilengths_idxs[is_indices[i]] = len+2;
4453     }
4454   }
4455   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
4456   /* additional is (if any) */
4457   if (nis) {
4458     PetscMPIInt psum;
4459     PetscInt j;
4460     for (j=0,psum=0;j<nis;j++) {
4461       PetscInt plen;
4462       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
4463       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
4464       psum += len+1; /* indices + lenght */
4465     }
4466     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
4467     for (j=0,psum=0;j<nis;j++) {
4468       PetscInt plen;
4469       const PetscInt *is_array_idxs;
4470       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
4471       send_buffer_idxs_is[psum] = plen;
4472       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
4473       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
4474       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
4475       psum += plen+1; /* indices + lenght */
4476     }
4477     for (i=0;i<n_sends;i++) {
4478       ilengths_idxs_is[is_indices[i]] = psum;
4479     }
4480     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
4481   }
4482 
4483   buf_size_idxs = 0;
4484   buf_size_vals = 0;
4485   buf_size_idxs_is = 0;
4486   for (i=0;i<n_recvs;i++) {
4487     buf_size_idxs += (PetscInt)olengths_idxs[i];
4488     buf_size_vals += (PetscInt)olengths_vals[i];
4489     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4490   }
4491   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4492   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
4493   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4494 
4495   /* get new tags for clean communications */
4496   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4497   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
4498   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4499 
4500   /* allocate for requests */
4501   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4502   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
4503   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4504   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4505   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
4506   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4507 
4508   /* communications */
4509   ptr_idxs = recv_buffer_idxs;
4510   ptr_vals = recv_buffer_vals;
4511   ptr_idxs_is = recv_buffer_idxs_is;
4512   for (i=0;i<n_recvs;i++) {
4513     source_dest = onodes[i];
4514     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4515     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4516     ptr_idxs += olengths_idxs[i];
4517     ptr_vals += olengths_vals[i];
4518     if (nis) {
4519       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);
4520       ptr_idxs_is += olengths_idxs_is[i];
4521     }
4522   }
4523   for (i=0;i<n_sends;i++) {
4524     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4525     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4526     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
4527     if (nis) {
4528       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);
4529     }
4530   }
4531   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4532   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4533 
4534   /* assemble new l2g map */
4535   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4536   ptr_idxs = recv_buffer_idxs;
4537   new_local_rows = 0;
4538   for (i=0;i<n_recvs;i++) {
4539     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4540     ptr_idxs += olengths_idxs[i];
4541   }
4542   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4543   ptr_idxs = recv_buffer_idxs;
4544   new_local_rows = 0;
4545   for (i=0;i<n_recvs;i++) {
4546     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
4547     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4548     ptr_idxs += olengths_idxs[i];
4549   }
4550   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
4551   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4552   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4553 
4554   /* infer new local matrix type from received local matrices type */
4555   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4556   /* 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) */
4557   if (n_recvs) {
4558     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4559     ptr_idxs = recv_buffer_idxs;
4560     for (i=0;i<n_recvs;i++) {
4561       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4562         new_local_type_private = MATAIJ_PRIVATE;
4563         break;
4564       }
4565       ptr_idxs += olengths_idxs[i];
4566     }
4567     switch (new_local_type_private) {
4568       case MATDENSE_PRIVATE:
4569         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4570           new_local_type = MATSEQAIJ;
4571           bs = 1;
4572         } else { /* if I receive only 1 dense matrix */
4573           new_local_type = MATSEQDENSE;
4574           bs = 1;
4575         }
4576         break;
4577       case MATAIJ_PRIVATE:
4578         new_local_type = MATSEQAIJ;
4579         bs = 1;
4580         break;
4581       case MATBAIJ_PRIVATE:
4582         new_local_type = MATSEQBAIJ;
4583         break;
4584       case MATSBAIJ_PRIVATE:
4585         new_local_type = MATSEQSBAIJ;
4586         break;
4587       default:
4588         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4589         break;
4590     }
4591   } else { /* by default, new_local_type is seqdense */
4592     new_local_type = MATSEQDENSE;
4593     bs = 1;
4594   }
4595 
4596   /* create MATIS object if needed */
4597   if (reuse == MAT_INITIAL_MATRIX) {
4598     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4599     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
4600   } else {
4601     /* it also destroys the local matrices */
4602     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
4603   }
4604   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4605   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
4606 
4607   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4608 
4609   /* Global to local map of received indices */
4610   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
4611   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
4612   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
4613 
4614   /* restore attributes -> type of incoming data and its size */
4615   buf_size_idxs = 0;
4616   for (i=0;i<n_recvs;i++) {
4617     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
4618     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
4619     buf_size_idxs += (PetscInt)olengths_idxs[i];
4620   }
4621   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
4622 
4623   /* set preallocation */
4624   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
4625   if (!newisdense) {
4626     PetscInt *new_local_nnz=0;
4627 
4628     ptr_vals = recv_buffer_vals;
4629     ptr_idxs = recv_buffer_idxs_local;
4630     if (n_recvs) {
4631       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
4632     }
4633     for (i=0;i<n_recvs;i++) {
4634       PetscInt j;
4635       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
4636         for (j=0;j<*(ptr_idxs+1);j++) {
4637           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
4638         }
4639       } else {
4640         /* TODO */
4641       }
4642       ptr_idxs += olengths_idxs[i];
4643     }
4644     if (new_local_nnz) {
4645       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
4646       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
4647       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
4648       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
4649       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
4650       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
4651     } else {
4652       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
4653     }
4654     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
4655   } else {
4656     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
4657   }
4658 
4659   /* set values */
4660   ptr_vals = recv_buffer_vals;
4661   ptr_idxs = recv_buffer_idxs_local;
4662   for (i=0;i<n_recvs;i++) {
4663     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4664       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
4665       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4666       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4667       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4668       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
4669     } else {
4670       /* TODO */
4671     }
4672     ptr_idxs += olengths_idxs[i];
4673     ptr_vals += olengths_vals[i];
4674   }
4675   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4676   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4677   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4678   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4679   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
4680   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4681 
4682 #if 0
4683   if (!restrict_comm) { /* check */
4684     Vec       lvec,rvec;
4685     PetscReal infty_error;
4686 
4687     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4688     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4689     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4690     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
4691     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4692     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4693     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4694     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4695     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4696   }
4697 #endif
4698 
4699   /* assemble new additional is (if any) */
4700   if (nis) {
4701     PetscInt **temp_idxs,*count_is,j,psum;
4702 
4703     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4704     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
4705     ptr_idxs = recv_buffer_idxs_is;
4706     psum = 0;
4707     for (i=0;i<n_recvs;i++) {
4708       for (j=0;j<nis;j++) {
4709         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
4710         count_is[j] += plen; /* increment counting of buffer for j-th IS */
4711         psum += plen;
4712         ptr_idxs += plen+1; /* shift pointer to received data */
4713       }
4714     }
4715     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4716     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
4717     for (i=1;i<nis;i++) {
4718       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
4719     }
4720     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
4721     ptr_idxs = recv_buffer_idxs_is;
4722     for (i=0;i<n_recvs;i++) {
4723       for (j=0;j<nis;j++) {
4724         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
4725         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
4726         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
4727         ptr_idxs += plen+1; /* shift pointer to received data */
4728       }
4729     }
4730     for (i=0;i<nis;i++) {
4731       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
4732       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
4733       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
4734     }
4735     ierr = PetscFree(count_is);CHKERRQ(ierr);
4736     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
4737     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
4738   }
4739   /* free workspace */
4740   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4741   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4742   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4743   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4744   if (isdense) {
4745     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4746     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4747   } else {
4748     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4749   }
4750   if (nis) {
4751     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4752     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
4753   }
4754   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4755   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
4756   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4757   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4758   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
4759   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4760   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4761   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4762   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4763   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4764   ierr = PetscFree(onodes);CHKERRQ(ierr);
4765   if (nis) {
4766     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
4767     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
4768     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
4769   }
4770   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4771   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
4772     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
4773     for (i=0;i<nis;i++) {
4774       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
4775     }
4776     *mat_n = NULL;
4777   }
4778   PetscFunctionReturn(0);
4779 }
4780 
4781 /* temporary hack into ksp private data structure */
4782 #include <petsc/private/kspimpl.h>
4783 
4784 #undef __FUNCT__
4785 #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4786 PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4787 {
4788   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4789   PC_IS                  *pcis = (PC_IS*)pc->data;
4790   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
4791   MatNullSpace           CoarseNullSpace=NULL;
4792   ISLocalToGlobalMapping coarse_islg;
4793   IS                     coarse_is,*isarray;
4794   PetscInt               i,im_active=-1,active_procs=-1;
4795   PetscInt               nis,nisdofs,nisneu,nisvert;
4796   PC                     pc_temp;
4797   PCType                 coarse_pc_type;
4798   KSPType                coarse_ksp_type;
4799   PetscBool              multilevel_requested,multilevel_allowed;
4800   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
4801   Mat                    t_coarse_mat_is;
4802   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
4803   PetscMPIInt            all_procs;
4804   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
4805   PetscBool              compute_vecs = PETSC_FALSE;
4806   PetscScalar            *array;
4807   PetscErrorCode         ierr;
4808 
4809   PetscFunctionBegin;
4810   /* Assign global numbering to coarse dofs */
4811   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 */
4812     PetscInt ocoarse_size;
4813     compute_vecs = PETSC_TRUE;
4814     ocoarse_size = pcbddc->coarse_size;
4815     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4816     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4817     /* see if we can avoid some work */
4818     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
4819       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
4820       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4821         PC        pc;
4822         PetscBool isbddc;
4823 
4824         /* temporary workaround since PCBDDC does not have a reset method so far */
4825         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4826         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4827         if (isbddc) {
4828           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4829         }
4830         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4831         coarse_reuse = PETSC_FALSE;
4832       } else { /* we can safely reuse already computed coarse matrix */
4833         coarse_reuse = PETSC_TRUE;
4834       }
4835     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4836       coarse_reuse = PETSC_FALSE;
4837     }
4838     /* reset any subassembling information */
4839     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
4840     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4841   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4842     coarse_reuse = PETSC_TRUE;
4843   }
4844 
4845   /* count "active" (i.e. with positive local size) and "void" processes */
4846   im_active = !!(pcis->n);
4847   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4848   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
4849   void_procs = all_procs-active_procs;
4850   csin_type_simple = PETSC_TRUE;
4851   redist = PETSC_FALSE;
4852   if (pcbddc->current_level && void_procs) {
4853     csin_ml = PETSC_TRUE;
4854     ncoarse_ml = void_procs;
4855     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4856     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
4857       csin_ds = PETSC_TRUE;
4858       ncoarse_ds = pcbddc->redistribute_coarse;
4859       redist = PETSC_TRUE;
4860     } else {
4861       csin_ds = PETSC_TRUE;
4862       ncoarse_ds = active_procs;
4863       redist = PETSC_TRUE;
4864     }
4865   } else {
4866     csin_ml = PETSC_FALSE;
4867     ncoarse_ml = all_procs;
4868     if (void_procs) {
4869       csin_ds = PETSC_TRUE;
4870       ncoarse_ds = void_procs;
4871       csin_type_simple = PETSC_FALSE;
4872     } else {
4873       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
4874         csin_ds = PETSC_TRUE;
4875         ncoarse_ds = pcbddc->redistribute_coarse;
4876         redist = PETSC_TRUE;
4877       } else {
4878         csin_ds = PETSC_FALSE;
4879         ncoarse_ds = all_procs;
4880       }
4881     }
4882   }
4883 
4884   /*
4885     test if we can go multilevel: three conditions must be satisfied:
4886     - we have not exceeded the number of levels requested
4887     - we can actually subassemble the active processes
4888     - we can find a suitable number of MPI processes where we can place the subassembled problem
4889   */
4890   multilevel_allowed = PETSC_FALSE;
4891   multilevel_requested = PETSC_FALSE;
4892   if (pcbddc->current_level < pcbddc->max_levels) {
4893     multilevel_requested = PETSC_TRUE;
4894     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4895       multilevel_allowed = PETSC_FALSE;
4896     } else {
4897       multilevel_allowed = PETSC_TRUE;
4898     }
4899   }
4900   /* determine number of process partecipating to coarse solver */
4901   if (multilevel_allowed) {
4902     ncoarse = ncoarse_ml;
4903     csin = csin_ml;
4904     redist = PETSC_FALSE;
4905   } else {
4906     ncoarse = ncoarse_ds;
4907     csin = csin_ds;
4908   }
4909 
4910   /* creates temporary l2gmap and IS for coarse indexes */
4911   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4912   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4913 
4914   /* creates temporary MATIS object for coarse matrix */
4915   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
4916   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4917   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
4918   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4919   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);
4920   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
4921   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4922   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4923   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4924 
4925   /* compute dofs splitting and neumann boundaries for coarse dofs */
4926   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
4927     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
4928     const PetscInt         *idxs;
4929     ISLocalToGlobalMapping tmap;
4930 
4931     /* create map between primal indices (in local representative ordering) and local primal numbering */
4932     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
4933     /* allocate space for temporary storage */
4934     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4935     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
4936     /* allocate for IS array */
4937     nisdofs = pcbddc->n_ISForDofsLocal;
4938     nisneu = !!pcbddc->NeumannBoundariesLocal;
4939     nisvert = 0;
4940     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
4941       nisvert = 1;
4942     }
4943     nis = nisdofs + nisneu + nisvert;
4944     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
4945     /* dofs splitting */
4946     for (i=0;i<nisdofs;i++) {
4947       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
4948       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
4949       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
4950       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
4951       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
4952       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4953       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
4954       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
4955     }
4956     /* neumann boundaries */
4957     if (pcbddc->NeumannBoundariesLocal) {
4958       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
4959       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
4960       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
4961       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
4962       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
4963       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4964       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
4965       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
4966     }
4967     /* primal vertices (benign) */
4968     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
4969       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
4970       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
4971       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
4972       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
4973       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4974       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
4975     }
4976     /* free memory */
4977     ierr = PetscFree(tidxs);CHKERRQ(ierr);
4978     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
4979     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
4980   } else {
4981     nis = 0;
4982     nisdofs = 0;
4983     nisneu = 0;
4984     nisvert = 0;
4985     isarray = NULL;
4986   }
4987   /* destroy no longer needed map */
4988   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
4989 
4990   /* restrict on coarse candidates (if needed) */
4991   coarse_mat_is = NULL;
4992   if (csin) {
4993     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
4994       if (redist) {
4995         PetscMPIInt rank;
4996         PetscInt    spc,n_spc_p1,dest[1],destsize;
4997 
4998         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
4999         spc = active_procs/ncoarse;
5000         n_spc_p1 = active_procs%ncoarse;
5001         if (im_active) {
5002           destsize = 1;
5003           if (rank > n_spc_p1*(spc+1)-1) {
5004             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
5005           } else {
5006             dest[0] = rank/(spc+1);
5007           }
5008         } else {
5009           destsize = 0;
5010         }
5011         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5012       } else if (csin_type_simple) {
5013         PetscMPIInt rank;
5014         PetscInt    issize,isidx;
5015 
5016         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
5017         if (im_active) {
5018           issize = 1;
5019           isidx = (PetscInt)rank;
5020         } else {
5021           issize = 0;
5022           isidx = -1;
5023         }
5024         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5025       } else { /* get a suitable subassembling pattern from MATIS code */
5026         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5027       }
5028 
5029       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5030       if (!redist || ncoarse <= void_procs) {
5031         PetscInt ncoarse_cand,tissize,*nisindices;
5032         PetscInt *coarse_candidates;
5033         const PetscInt* tisindices;
5034 
5035         /* get coarse candidates' ranks in pc communicator */
5036         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5037         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5038         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5039           if (!coarse_candidates[i]) {
5040             coarse_candidates[ncoarse_cand++]=i;
5041           }
5042         }
5043         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5044 
5045 
5046         if (pcbddc->dbg_flag) {
5047           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5048           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
5049           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
5050           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5051           for (i=0;i<ncoarse_cand;i++) {
5052             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
5053           }
5054           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
5055           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5056         }
5057         /* shift the pattern on coarse candidates */
5058         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
5059         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5060         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
5061         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
5062         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5063         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
5064         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
5065       }
5066       if (pcbddc->dbg_flag) {
5067         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5068         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
5069         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
5070         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5071       }
5072     }
5073     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
5074     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
5075       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_FALSE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
5076     } else { /* this is the last level, so use just receiving processes in subcomm */
5077       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
5078     }
5079   } else {
5080     if (pcbddc->dbg_flag) {
5081       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5082       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
5083       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5084     }
5085     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
5086     coarse_mat_is = t_coarse_mat_is;
5087   }
5088 
5089   /* create local to global scatters for coarse problem */
5090   if (compute_vecs) {
5091     PetscInt lrows;
5092     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
5093     if (coarse_mat_is) {
5094       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
5095     } else {
5096       lrows = 0;
5097     }
5098     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
5099     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
5100     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
5101     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
5102     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
5103   }
5104   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5105   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5106 
5107   /* set defaults for coarse KSP and PC */
5108   if (multilevel_allowed) {
5109     coarse_ksp_type = KSPRICHARDSON;
5110     coarse_pc_type = PCBDDC;
5111   } else {
5112     coarse_ksp_type = KSPPREONLY;
5113     coarse_pc_type = PCREDUNDANT;
5114   }
5115 
5116   /* print some info if requested */
5117   if (pcbddc->dbg_flag) {
5118     if (!multilevel_allowed) {
5119       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5120       if (multilevel_requested) {
5121         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);
5122       } else if (pcbddc->max_levels) {
5123         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
5124       }
5125       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5126     }
5127   }
5128 
5129   /* create the coarse KSP object only once with defaults */
5130   if (coarse_mat_is) {
5131     MatReuse coarse_mat_reuse;
5132     PetscViewer dbg_viewer = NULL;
5133     if (pcbddc->dbg_flag) {
5134       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
5135       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
5136     }
5137     if (!pcbddc->coarse_ksp) {
5138       char prefix[256],str_level[16];
5139       size_t len;
5140       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5141       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5142       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5143       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
5144       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5145       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
5146       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5147       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5148       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5149       /* prefix */
5150       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5151       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5152       if (!pcbddc->current_level) {
5153         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5154         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5155       } else {
5156         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5157         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5158         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
5159         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5160         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5161         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5162       }
5163       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
5164       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
5165       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
5166       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
5167       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5168       /* allow user customization */
5169       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
5170     }
5171     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
5172     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5173     if (nisdofs) {
5174       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
5175       for (i=0;i<nisdofs;i++) {
5176         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
5177       }
5178     }
5179     if (nisneu) {
5180       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
5181       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5182     }
5183     if (nisvert) {
5184       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
5185       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
5186     }
5187 
5188     /* get some info after set from options */
5189     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5190     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
5191     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
5192     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5193       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5194       isbddc = PETSC_FALSE;
5195     }
5196     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
5197     if (isredundant) {
5198       KSP inner_ksp;
5199       PC  inner_pc;
5200       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
5201       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
5202       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
5203     }
5204 
5205     /* assemble coarse matrix */
5206     if (coarse_reuse) {
5207       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5208       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
5209       coarse_mat_reuse = MAT_REUSE_MATRIX;
5210     } else {
5211       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5212     }
5213     if (isbddc || isnn) {
5214       if (pcbddc->coarsening_ratio > 1) {
5215         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5216           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
5217           if (pcbddc->dbg_flag) {
5218             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5219             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
5220             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
5221             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
5222           }
5223         }
5224         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
5225       } else {
5226         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
5227         coarse_mat = coarse_mat_is;
5228       }
5229     } else {
5230       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5231     }
5232     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5233 
5234     /* propagate symmetry info of coarse matrix */
5235     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
5236     if (pc->pmat->symmetric_set) {
5237       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
5238     }
5239     if (pc->pmat->hermitian_set) {
5240       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
5241     }
5242     if (pc->pmat->spd_set) {
5243       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
5244     }
5245     /* set operators */
5246     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5247     if (pcbddc->dbg_flag) {
5248       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
5249     }
5250   } else { /* processes non partecipating to coarse solver (if any) */
5251     coarse_mat = 0;
5252   }
5253   ierr = PetscFree(isarray);CHKERRQ(ierr);
5254 #if 0
5255   {
5256     PetscViewer viewer;
5257     char filename[256];
5258     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5259     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5260     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5261     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5262     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5263   }
5264 #endif
5265 
5266   /* Compute coarse null space (special handling by BDDC only) */
5267 #if 0
5268   if (pcbddc->NullSpace) {
5269     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
5270   }
5271 #endif
5272   /* hack */
5273   if (pcbddc->coarse_ksp) {
5274     Vec crhs,csol;
5275 
5276     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5277     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5278     if (!csol) {
5279       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5280     }
5281     if (!crhs) {
5282       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5283     }
5284   }
5285 
5286   /* compute null space for coarse solver if the benign trick has been requested */
5287   if (pcbddc->benign_null) {
5288 
5289     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
5290     for (i=0;i<pcbddc->benign_n;i++) {
5291       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
5292     }
5293     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5294     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5295     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5296     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5297     if (coarse_mat) {
5298       Vec         nullv;
5299       PetscScalar *array,*array2;
5300       PetscInt    nl;
5301 
5302       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5303       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5304       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5305       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5306       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5307       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5308       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5309       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5310       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5311       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5312     }
5313   }
5314 
5315   if (pcbddc->coarse_ksp) {
5316     PetscBool ispreonly;
5317 
5318     if (CoarseNullSpace) {
5319       PetscBool isnull;
5320       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5321       if (isnull) {
5322         if (isbddc && !pcbddc->benign_saddle_point) {
5323           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5324         } else {
5325           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5326         }
5327       } else {
5328         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5329       }
5330     }
5331     /* setup coarse ksp */
5332     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5333     /* Check coarse problem if in debug mode or if solving with an iterative method */
5334     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
5335     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5336       KSP       check_ksp;
5337       KSPType   check_ksp_type;
5338       PC        check_pc;
5339       Vec       check_vec,coarse_vec;
5340       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
5341       PetscInt  its;
5342       PetscBool compute_eigs;
5343       PetscReal *eigs_r,*eigs_c;
5344       PetscInt  neigs;
5345       const char *prefix;
5346 
5347       /* Create ksp object suitable for estimation of extreme eigenvalues */
5348       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5349       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5350       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5351       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
5352       if (ispreonly) {
5353         check_ksp_type = KSPPREONLY;
5354         compute_eigs = PETSC_FALSE;
5355       } else {
5356         check_ksp_type = KSPGMRES;
5357         compute_eigs = PETSC_TRUE;
5358       }
5359       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
5360       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
5361       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
5362       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5363       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5364       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5365       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5366       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5367       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5368       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5369       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5370       /* create random vec */
5371       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
5372       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5373       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5374       if (CoarseNullSpace) {
5375         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5376       }
5377       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5378       /* solve coarse problem */
5379       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5380       if (CoarseNullSpace) {
5381         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5382       }
5383       /* set eigenvalue estimation if preonly has not been requested */
5384       if (compute_eigs) {
5385         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5386         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
5387         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
5388         lambda_max = eigs_r[neigs-1];
5389         lambda_min = eigs_r[0];
5390         if (pcbddc->use_coarse_estimates) {
5391           if (lambda_max>lambda_min) {
5392             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5393             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5394           }
5395         }
5396       }
5397 
5398       /* check coarse problem residual error */
5399       if (pcbddc->dbg_flag) {
5400         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
5401         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
5402         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5403         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5404         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5405         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5406         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5407         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
5408         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
5409         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
5410         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
5411         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5412         if (CoarseNullSpace) {
5413           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5414         }
5415         if (compute_eigs) {
5416           PetscReal lambda_max_s,lambda_min_s;
5417           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5418           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
5419           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
5420           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);
5421           for (i=0;i<neigs;i++) {
5422             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5423           }
5424         }
5425         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
5426         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
5427       }
5428       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
5429       if (compute_eigs) {
5430         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
5431         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5432       }
5433     }
5434   }
5435   /* print additional info */
5436   if (pcbddc->dbg_flag) {
5437     /* waits until all processes reaches this point */
5438     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5439     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5440     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5441   }
5442 
5443   /* free memory */
5444   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5445   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5446   PetscFunctionReturn(0);
5447 }
5448 
5449 #undef __FUNCT__
5450 #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5451 PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5452 {
5453   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5454   PC_IS*         pcis = (PC_IS*)pc->data;
5455   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5456   IS             subset,subset_mult,subset_n;
5457   PetscInt       local_size,coarse_size=0;
5458   PetscInt       *local_primal_indices=NULL;
5459   const PetscInt *t_local_primal_indices;
5460   PetscErrorCode ierr;
5461 
5462   PetscFunctionBegin;
5463   /* Compute global number of coarse dofs */
5464   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
5465     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5466   }
5467   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
5468   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5469   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5470   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5471   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5472   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5473   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5474   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
5475   if (local_size != pcbddc->local_primal_size) {
5476     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
5477   }
5478   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5479   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5480   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5481   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5482   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5483 
5484   /* check numbering */
5485   if (pcbddc->dbg_flag) {
5486     PetscScalar coarsesum,*array,*array2;
5487     PetscInt    i;
5488     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5489 
5490     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5491     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5492     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
5493     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5494     /* counter */
5495     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5496     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5497     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5498     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5499     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5500     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5501 
5502     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5503     for (i=0;i<pcbddc->local_primal_size;i++) {
5504       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5505     }
5506     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5507     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5508     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5509     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5510     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5511     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5512     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5513     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5514     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5515     for (i=0;i<pcis->n;i++) {
5516       if (array[i] != 0.0 && array[i] != array2[i]) {
5517         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
5518         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5519         set_error = PETSC_TRUE;
5520         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a %d processes instead of %d!\n",PetscGlobalRank,i,owned,neigh);CHKERRQ(ierr);
5521       }
5522     }
5523     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5524     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5525     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5526     for (i=0;i<pcis->n;i++) {
5527       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5528     }
5529     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5530     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5531     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5532     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5533     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5534     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5535     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5536       PetscInt *gidxs;
5537 
5538       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
5539       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5540       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5541       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5542       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5543       for (i=0;i<pcbddc->local_primal_size;i++) {
5544         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);
5545       }
5546       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5547       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5548     }
5549     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5550     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5551   }
5552   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5553   /* get back data */
5554   *coarse_size_n = coarse_size;
5555   *local_primal_indices_n = local_primal_indices;
5556   PetscFunctionReturn(0);
5557 }
5558 
5559 #undef __FUNCT__
5560 #define __FUNCT__ "PCBDDCGlobalToLocal"
5561 PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5562 {
5563   IS             localis_t;
5564   PetscInt       i,lsize,*idxs,n;
5565   PetscScalar    *vals;
5566   PetscErrorCode ierr;
5567 
5568   PetscFunctionBegin;
5569   /* get indices in local ordering exploiting local to global map */
5570   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5571   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5572   for (i=0;i<lsize;i++) vals[i] = 1.0;
5573   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5574   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5575   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
5576   if (idxs) { /* multilevel guard */
5577     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
5578   }
5579   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5580   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5581   ierr = PetscFree(vals);CHKERRQ(ierr);
5582   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5583   /* now compute set in local ordering */
5584   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5585   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5586   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5587   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5588   for (i=0,lsize=0;i<n;i++) {
5589     if (PetscRealPart(vals[i]) > 0.5) {
5590       lsize++;
5591     }
5592   }
5593   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5594   for (i=0,lsize=0;i<n;i++) {
5595     if (PetscRealPart(vals[i]) > 0.5) {
5596       idxs[lsize++] = i;
5597     }
5598   }
5599   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5600   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5601   *localis = localis_t;
5602   PetscFunctionReturn(0);
5603 }
5604 
5605 /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5606 #undef __FUNCT__
5607 #define __FUNCT__ "PCBDDCMatMult_Private"
5608 static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5609 {
5610   PCBDDCChange_ctx change_ctx;
5611   PetscErrorCode   ierr;
5612 
5613   PetscFunctionBegin;
5614   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5615   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5616   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5617   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5618   PetscFunctionReturn(0);
5619 }
5620 
5621 #undef __FUNCT__
5622 #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5623 static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5624 {
5625   PCBDDCChange_ctx change_ctx;
5626   PetscErrorCode   ierr;
5627 
5628   PetscFunctionBegin;
5629   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5630   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5631   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5632   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5633   PetscFunctionReturn(0);
5634 }
5635 
5636 #undef __FUNCT__
5637 #define __FUNCT__ "PCBDDCSetUpSubSchurs"
5638 PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5639 {
5640   PC_IS               *pcis=(PC_IS*)pc->data;
5641   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5642   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5643   Mat                 S_j;
5644   PetscInt            *used_xadj,*used_adjncy;
5645   PetscBool           free_used_adj;
5646   PetscErrorCode      ierr;
5647 
5648   PetscFunctionBegin;
5649   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5650   free_used_adj = PETSC_FALSE;
5651   if (pcbddc->sub_schurs_layers == -1) {
5652     used_xadj = NULL;
5653     used_adjncy = NULL;
5654   } else {
5655     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
5656       used_xadj = pcbddc->mat_graph->xadj;
5657       used_adjncy = pcbddc->mat_graph->adjncy;
5658     } else if (pcbddc->computed_rowadj) {
5659       used_xadj = pcbddc->mat_graph->xadj;
5660       used_adjncy = pcbddc->mat_graph->adjncy;
5661     } else {
5662       PetscBool      flg_row=PETSC_FALSE;
5663       const PetscInt *xadj,*adjncy;
5664       PetscInt       nvtxs;
5665 
5666       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5667       if (flg_row) {
5668         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5669         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5670         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5671         free_used_adj = PETSC_TRUE;
5672       } else {
5673         pcbddc->sub_schurs_layers = -1;
5674         used_xadj = NULL;
5675         used_adjncy = NULL;
5676       }
5677       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5678     }
5679   }
5680 
5681   /* setup sub_schurs data */
5682   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5683   if (!sub_schurs->use_mumps) {
5684     /* pcbddc->ksp_D up to date only if not using MUMPS */
5685     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5686     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE);CHKERRQ(ierr);
5687   } else {
5688     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
5689     PetscBool isseqaij;
5690     if (!pcbddc->use_vertices && reuse_solvers) {
5691       PetscInt n_vertices;
5692 
5693       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
5694       reuse_solvers = (PetscBool)!n_vertices;
5695     }
5696     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
5697     if (!isseqaij) {
5698       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
5699       if (matis->A == pcbddc->local_mat) {
5700         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
5701         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5702       } else {
5703         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
5704       }
5705     }
5706     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,pcbddc->faster_deluxe,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point);CHKERRQ(ierr);
5707   }
5708   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5709 
5710   /* free adjacency */
5711   if (free_used_adj) {
5712     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5713   }
5714   PetscFunctionReturn(0);
5715 }
5716 
5717 #undef __FUNCT__
5718 #define __FUNCT__ "PCBDDCInitSubSchurs"
5719 PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5720 {
5721   PC_IS               *pcis=(PC_IS*)pc->data;
5722   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5723   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5724   PCBDDCGraph         graph;
5725   PetscErrorCode      ierr;
5726 
5727   PetscFunctionBegin;
5728   /* attach interface graph for determining subsets */
5729   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
5730     IS       verticesIS,verticescomm;
5731     PetscInt vsize,*idxs;
5732 
5733     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
5734     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
5735     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
5736     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
5737     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
5738     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5739     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
5740     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
5741     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
5742     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5743     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5744 /*
5745     if (pcbddc->dbg_flag) {
5746       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5747     }
5748 */
5749   } else {
5750     graph = pcbddc->mat_graph;
5751   }
5752 
5753   /* sub_schurs init */
5754   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5755 
5756   /* free graph struct */
5757   if (pcbddc->sub_schurs_rebuild) {
5758     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5759   }
5760   PetscFunctionReturn(0);
5761 }
5762 
5763 #undef __FUNCT__
5764 #define __FUNCT__ "PCBDDCCheckOperator"
5765 PetscErrorCode PCBDDCCheckOperator(PC pc)
5766 {
5767   PC_IS               *pcis=(PC_IS*)pc->data;
5768   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5769   PetscErrorCode      ierr;
5770 
5771   PetscFunctionBegin;
5772   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5773     IS             zerodiag = NULL;
5774     Mat            S_j,B0_B=NULL;
5775     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
5776     PetscScalar    *p0_check,*array,*array2;
5777     PetscReal      norm;
5778     PetscInt       i;
5779 
5780     /* B0 and B0_B */
5781     if (zerodiag) {
5782       IS       dummy;
5783 
5784       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
5785       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5786       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5787       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5788     }
5789     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5790     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5791     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5792     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5793     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5794     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5795     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5796     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5797     /* S_j */
5798     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5799     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5800 
5801     /* mimic vector in \widetilde{W}_\Gamma */
5802     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5803     /* continuous in primal space */
5804     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5805     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5806     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5807     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5808     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
5809     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
5810     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5811     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5812     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5813     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5814     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5815     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5816     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5817     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5818 
5819     /* assemble rhs for coarse problem */
5820     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5821     /* local with Schur */
5822     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5823     if (zerodiag) {
5824       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5825       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
5826       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5827       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5828     }
5829     /* sum on primal nodes the local contributions */
5830     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5831     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5832     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5833     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5834     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5835     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5836     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5837     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5838     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5839     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5840     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5841     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5842     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5843     /* scale primal nodes (BDDC sums contibutions) */
5844     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5845     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5846     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5847     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5848     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5849     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5850     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5851     /* global: \widetilde{B0}_B w_\Gamma */
5852     if (zerodiag) {
5853       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5854       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
5855       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
5856       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5857     }
5858     /* BDDC */
5859     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5860     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5861 
5862     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5863     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5864     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5865     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
5866     for (i=0;i<pcbddc->benign_n;i++) {
5867       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
5868     }
5869     ierr = PetscFree(p0_check);CHKERRQ(ierr);
5870     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5871     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5872     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5873     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5874     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5875   }
5876   PetscFunctionReturn(0);
5877 }
5878