xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision ae9be28942d2d3eca8476af0b23adcfdc0f3733e)
1 /* TODOLIST
2    Exact solvers: Solve local saddle point directly for very hard problems
3    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
4    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
5      - mind the problem with coarsening_factor
6      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
7      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
8      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
9      - Add levels' slot to bddc data structure and associated Set/Get functions
10    code refactoring:
11      - pick up better names for static functions
12    check log_summary for leaking (actually: 1 Vector per level )
13    change options structure:
14      - insert BDDC into MG framework?
15    provide other ops? Ask to developers
16    remove all unused printf
17    remove // commments and adhere to PETSc code requirements
18    man pages
19 */
20 
21 /* ----------------------------------------------------------------------------------------------------------------------------------------------
22    Implementation of BDDC preconditioner based on:
23    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
24    ---------------------------------------------------------------------------------------------------------------------------------------------- */
25 
26 #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
27 #include <petscblaslapack.h>
28 
29 /* -------------------------------------------------------------------------- */
30 #undef __FUNCT__
31 #define __FUNCT__ "PCSetFromOptions_BDDC"
32 PetscErrorCode PCSetFromOptions_BDDC(PC pc)
33 {
34   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
35   PetscErrorCode ierr;
36 
37   PetscFunctionBegin;
38   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
39   /* Verbose debugging of main data structures */
40   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
41   /* Some customization for default primal space */
42   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
43   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
44   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use faces only in coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
45   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use edges only in coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
46   /* Coarse solver context */
47   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
48   ierr = PetscOptionsEnum("-pc_bddc_coarse_problem_type","Set coarse problem type","none",avail_coarse_problems,(PetscEnum)pcbddc->coarse_problem_type,(PetscEnum*)&pcbddc->coarse_problem_type,PETSC_NULL);CHKERRQ(ierr);
49   /* Two different application of BDDC to the whole set of dofs, internal and interface */
50   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->prec_type,&pcbddc->prec_type,PETSC_NULL);CHKERRQ(ierr);
51   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr);
52   ierr = PetscOptionsTail();CHKERRQ(ierr);
53   PetscFunctionReturn(0);
54 }
55 
56 /* -------------------------------------------------------------------------- */
57 EXTERN_C_BEGIN
58 #undef __FUNCT__
59 #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
60 static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
61 {
62   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
63 
64   PetscFunctionBegin;
65   pcbddc->coarse_problem_type = CPT;
66   PetscFunctionReturn(0);
67 }
68 EXTERN_C_END
69 
70 /* -------------------------------------------------------------------------- */
71 #undef __FUNCT__
72 #define __FUNCT__ "PCBDDCSetCoarseProblemType"
73 /*@
74  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
75 
76    Not collective
77 
78    Input Parameters:
79 +  pc - the preconditioning context
80 -  CoarseProblemType - pick a better name and explain what this is
81 
82    Level: intermediate
83 
84    Notes:
85    Not collective but all procs must call this.
86 
87 .seealso: PCBDDC
88 @*/
89 PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
90 {
91   PetscErrorCode ierr;
92 
93   PetscFunctionBegin;
94   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
95   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
96   PetscFunctionReturn(0);
97 }
98 
99 /* -------------------------------------------------------------------------- */
100 EXTERN_C_BEGIN
101 #undef __FUNCT__
102 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
103 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
104 {
105   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
106   PetscErrorCode ierr;
107 
108   PetscFunctionBegin;
109   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
110   ierr = ISDuplicate(DirichletBoundaries,&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
111   ierr = ISCopy(DirichletBoundaries,pcbddc->DirichletBoundaries);CHKERRQ(ierr);
112   PetscFunctionReturn(0);
113 }
114 EXTERN_C_END
115 
116 /* -------------------------------------------------------------------------- */
117 #undef __FUNCT__
118 #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
119 /*@
120  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part of
121                               Dirichlet boundaries for the global problem.
122 
123    Not collective
124 
125    Input Parameters:
126 +  pc - the preconditioning context
127 -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
128 
129    Level: intermediate
130 
131    Notes:
132    The sequential IS is copied; the user must destroy the IS object passed in.
133 
134 .seealso: PCBDDC
135 @*/
136 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
137 {
138   PetscErrorCode ierr;
139 
140   PetscFunctionBegin;
141   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
142   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
143   PetscFunctionReturn(0);
144 }
145 /* -------------------------------------------------------------------------- */
146 EXTERN_C_BEGIN
147 #undef __FUNCT__
148 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
149 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
150 {
151   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
152   PetscErrorCode ierr;
153 
154   PetscFunctionBegin;
155   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
156   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
157   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
158   PetscFunctionReturn(0);
159 }
160 EXTERN_C_END
161 
162 /* -------------------------------------------------------------------------- */
163 #undef __FUNCT__
164 #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
165 /*@
166  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
167                               Neumann boundaries for the global problem.
168 
169    Not collective
170 
171    Input Parameters:
172 +  pc - the preconditioning context
173 -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
174 
175    Level: intermediate
176 
177    Notes:
178    The sequential IS is copied; the user must destroy the IS object passed in.
179 
180 .seealso: PCBDDC
181 @*/
182 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
183 {
184   PetscErrorCode ierr;
185 
186   PetscFunctionBegin;
187   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
188   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
189   PetscFunctionReturn(0);
190 }
191 /* -------------------------------------------------------------------------- */
192 EXTERN_C_BEGIN
193 #undef __FUNCT__
194 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
195 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
196 {
197   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
198 
199   PetscFunctionBegin;
200   if(pcbddc->NeumannBoundaries) {
201     *NeumannBoundaries = pcbddc->NeumannBoundaries;
202   } else {
203     *NeumannBoundaries = PETSC_NULL;
204     //SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
205   }
206   PetscFunctionReturn(0);
207 }
208 EXTERN_C_END
209 
210 /* -------------------------------------------------------------------------- */
211 #undef __FUNCT__
212 #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
213 /*@
214  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
215                               Neumann boundaries for the global problem.
216 
217    Not collective
218 
219    Input Parameters:
220 +  pc - the preconditioning context
221 
222    Output Parameters:
223 +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
224 
225    Level: intermediate
226 
227    Notes:
228    If the user has not yet provided such information, PETSC_NULL is returned.
229 
230 .seealso: PCBDDC
231 @*/
232 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
233 {
234   PetscErrorCode ierr;
235 
236   PetscFunctionBegin;
237   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
238   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
239   PetscFunctionReturn(0);
240 }
241 
242 /* -------------------------------------------------------------------------- */
243 EXTERN_C_BEGIN
244 #undef __FUNCT__
245 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
246 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
247 {
248   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
249   PetscInt i;
250   PetscErrorCode ierr;
251 
252   PetscFunctionBegin;
253   /* Destroy IS if already set */
254   for(i=0;i<pcbddc->n_ISForDofs;i++) {
255     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
256     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
257     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
258   }
259   /* allocate space then copy ISs */
260   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
261   for(i=0;i<n_is;i++) {
262     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
263     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
264   }
265   pcbddc->n_ISForDofs=n_is;
266   PetscFunctionReturn(0);
267 }
268 EXTERN_C_END
269 
270 /* -------------------------------------------------------------------------- */
271 #undef __FUNCT__
272 #define __FUNCT__ "PCBDDCSetDofsSplitting"
273 /*@
274  PCBDDCSetDofsSplitting - Set index set defining how dofs are splitted.
275 
276    Not collective
277 
278    Input Parameters:
279 +  pc - the preconditioning context
280 -  n - number of index sets defining dofs spltting
281 -  IS[] - array of IS describing dofs splitting
282 
283    Level: intermediate
284 
285    Notes:
286    Sequential ISs are copied, the user must destroy the array of IS passed in.
287 
288 .seealso: PCBDDC
289 @*/
290 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
291 {
292   PetscErrorCode ierr;
293 
294   PetscFunctionBegin;
295   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
296   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
297   PetscFunctionReturn(0);
298 }
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "PCSetUp_BDDC"
302 /* -------------------------------------------------------------------------- */
303 /*
304    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
305                   by setting data structures and options.
306 
307    Input Parameter:
308 +  pc - the preconditioner context
309 
310    Application Interface Routine: PCSetUp()
311 
312    Notes:
313    The interface routine PCSetUp() is not usually called directly by
314    the user, but instead is called by PCApply() if necessary.
315 */
316 PetscErrorCode PCSetUp_BDDC(PC pc)
317 {
318   PetscErrorCode ierr;
319   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
320   PC_IS            *pcis = (PC_IS*)(pc->data);
321 
322   PetscFunctionBegin;
323   if (!pc->setupcalled) {
324     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
325        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
326        Also, we decide to directly build the (same) Dirichlet problem */
327     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
328     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
329     /* Set up all the "iterative substructuring" common block */
330     ierr = PCISSetUp(pc);CHKERRQ(ierr);
331     /* Get stdout for dbg */
332     if(pcbddc->dbg_flag) {
333       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
334       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
335     }
336     /* TODO MOVE CODE FRAGMENT */
337     PetscInt im_active=0;
338     if(pcis->n) im_active = 1;
339     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
340     /* Analyze local interface */
341     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
342     /* Set up local constraint matrix */
343     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
344     /* Create coarse and local stuffs used for evaluating action of preconditioner */
345     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
346     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
347     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
348   }
349   PetscFunctionReturn(0);
350 }
351 
352 /* -------------------------------------------------------------------------- */
353 /*
354    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
355 
356    Input Parameters:
357 .  pc - the preconditioner context
358 .  r - input vector (global)
359 
360    Output Parameter:
361 .  z - output vector (global)
362 
363    Application Interface Routine: PCApply()
364  */
365 #undef __FUNCT__
366 #define __FUNCT__ "PCApply_BDDC"
367 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
368 {
369   PC_IS             *pcis = (PC_IS*)(pc->data);
370   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
371   PetscErrorCode    ierr;
372   const PetscScalar one = 1.0;
373   const PetscScalar m_one = -1.0;
374 
375 /* This code is similar to that provided in nn.c for PCNN
376    NN interface preconditioner changed to BDDC
377    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
378 
379   PetscFunctionBegin;
380   /* First Dirichlet solve */
381   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
382   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
383   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
384   /*
385     Assembling right hand side for BDDC operator
386     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
387     - the interface part of the global vector z
388   */
389   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
390   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
391   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
392   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
393   ierr = VecCopy(r,z);CHKERRQ(ierr);
394   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
395   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
396 
397   /*
398     Apply interface preconditioner
399     Results are stored in:
400     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
401     -  the interface part of the global vector z
402   */
403   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
404 
405   /* Second Dirichlet solve and assembling of output */
406   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
407   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
408   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
409   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
410   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
411   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
412   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
413   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
414   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
415   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
416 
417   PetscFunctionReturn(0);
418 
419 }
420 
421 /* -------------------------------------------------------------------------- */
422 /*
423    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
424 
425 */
426 #undef __FUNCT__
427 #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
428 static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
429 {
430   PetscErrorCode ierr;
431   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
432   PC_IS*            pcis = (PC_IS*)  (pc->data);
433   const PetscScalar zero = 0.0;
434 
435   PetscFunctionBegin;
436   /* Get Local boundary and apply partition of unity */
437   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
438   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
439   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
440 
441   /* Application of PHI^T  */
442   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
443   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
444 
445   /* Scatter data of coarse_rhs */
446   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
447   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448 
449   /* Local solution on R nodes */
450   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
451   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
452   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
453   if(pcbddc->prec_type) {
454     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
455     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
456   }
457   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
458   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
459   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
460   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
461   if(pcbddc->prec_type) {
462     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
463     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
464   }
465 
466   /* Coarse solution */
467   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
468   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
469   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
470   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
471 
472   /* Sum contributions from two levels */
473   /* Apply partition of unity and sum boundary values */
474   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
475   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
476   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
477   ierr = VecSet(z,zero);CHKERRQ(ierr);
478   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
479   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
480 
481   PetscFunctionReturn(0);
482 }
483 
484 
485 /* -------------------------------------------------------------------------- */
486 /*
487    PCBDDCSolveSaddlePoint
488 
489 */
490 #undef __FUNCT__
491 #define __FUNCT__ "PCBDDCSolveSaddlePoint"
492 static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
493 {
494   PetscErrorCode ierr;
495   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
496 
497   PetscFunctionBegin;
498 
499   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
500   if(pcbddc->n_constraints) {
501     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
502     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
503   }
504 
505   PetscFunctionReturn(0);
506 }
507 /* -------------------------------------------------------------------------- */
508 /*
509    PCBDDCScatterCoarseDataBegin
510 
511 */
512 #undef __FUNCT__
513 #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
514 static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
515 {
516   PetscErrorCode ierr;
517   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
518 
519   PetscFunctionBegin;
520 
521   switch(pcbddc->coarse_communications_type){
522     case SCATTERS_BDDC:
523       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
524       break;
525     case GATHERS_BDDC:
526       break;
527   }
528   PetscFunctionReturn(0);
529 
530 }
531 /* -------------------------------------------------------------------------- */
532 /*
533    PCBDDCScatterCoarseDataEnd
534 
535 */
536 #undef __FUNCT__
537 #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
538 static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
539 {
540   PetscErrorCode ierr;
541   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
542   PetscScalar*   array_to;
543   PetscScalar*   array_from;
544   MPI_Comm       comm=((PetscObject)pc)->comm;
545   PetscInt i;
546 
547   PetscFunctionBegin;
548 
549   switch(pcbddc->coarse_communications_type){
550     case SCATTERS_BDDC:
551       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
552       break;
553     case GATHERS_BDDC:
554       if(vec_from) VecGetArray(vec_from,&array_from);
555       if(vec_to)   VecGetArray(vec_to,&array_to);
556       switch(pcbddc->coarse_problem_type){
557         case SEQUENTIAL_BDDC:
558           if(smode == SCATTER_FORWARD) {
559             ierr = MPI_Gatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
560             if(vec_to) {
561               for(i=0;i<pcbddc->replicated_primal_size;i++)
562                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
563             }
564           } else {
565             if(vec_from)
566               for(i=0;i<pcbddc->replicated_primal_size;i++)
567                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
568             ierr = MPI_Scatterv(&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,&array_to[0],pcbddc->local_primal_size,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
569           }
570           break;
571         case REPLICATED_BDDC:
572           if(smode == SCATTER_FORWARD) {
573             ierr = MPI_Allgatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,comm);CHKERRQ(ierr);
574             for(i=0;i<pcbddc->replicated_primal_size;i++)
575               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
576           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
577             for(i=0;i<pcbddc->local_primal_size;i++)
578               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
579           }
580           break;
581         case MULTILEVEL_BDDC:
582           break;
583         case PARALLEL_BDDC:
584           break;
585       }
586       if(vec_from) VecRestoreArray(vec_from,&array_from);
587       if(vec_to)   VecRestoreArray(vec_to,&array_to);
588       break;
589   }
590   PetscFunctionReturn(0);
591 
592 }
593 
594 /* -------------------------------------------------------------------------- */
595 /*
596    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
597    that was created with PCCreate_BDDC().
598 
599    Input Parameter:
600 .  pc - the preconditioner context
601 
602    Application Interface Routine: PCDestroy()
603 */
604 #undef __FUNCT__
605 #define __FUNCT__ "PCDestroy_BDDC"
606 PetscErrorCode PCDestroy_BDDC(PC pc)
607 {
608   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
609   PetscErrorCode ierr;
610 
611   PetscFunctionBegin;
612   /* free data created by PCIS */
613   ierr = PCISDestroy(pc);CHKERRQ(ierr);
614   /* free BDDC data  */
615   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
616   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
617   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
618   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
619   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
620   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
621   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
622   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
623   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
624   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
625   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
626   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
627   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
628   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
629   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
630   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
631   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
632   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
633   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
634   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
635   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
636   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
637   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
638   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
639   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
640   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
641   PetscInt i;
642   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
643   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
644   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
645   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
646   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
647   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
648   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
649   /* Free the private data structure that was hanging off the PC */
650   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
651   PetscFunctionReturn(0);
652 }
653 
654 /* -------------------------------------------------------------------------- */
655 /*MC
656    PCBDDC - Balancing Domain Decomposition by Constraints.
657 
658    Options Database Keys:
659 .    -pcbddc ??? -
660 
661    Level: intermediate
662 
663    Notes: The matrix used with this preconditioner must be of type MATIS
664 
665           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
666           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
667           on the subdomains).
668 
669           Options for the coarse grid preconditioner can be set with -
670           Options for the Dirichlet subproblem can be set with -
671           Options for the Neumann subproblem can be set with -
672 
673    Contributed by Stefano Zampini
674 
675 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
676 M*/
677 EXTERN_C_BEGIN
678 #undef __FUNCT__
679 #define __FUNCT__ "PCCreate_BDDC"
680 PetscErrorCode PCCreate_BDDC(PC pc)
681 {
682   PetscErrorCode ierr;
683   PC_BDDC          *pcbddc;
684 
685   PetscFunctionBegin;
686   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
687   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
688   pc->data  = (void*)pcbddc;
689   /* create PCIS data structure */
690   ierr = PCISCreate(pc);CHKERRQ(ierr);
691   /* BDDC specific */
692   pcbddc->coarse_vec                 = 0;
693   pcbddc->coarse_rhs                 = 0;
694   pcbddc->coarse_ksp                 = 0;
695   pcbddc->coarse_phi_B               = 0;
696   pcbddc->coarse_phi_D               = 0;
697   pcbddc->vec1_P                     = 0;
698   pcbddc->vec1_R                     = 0;
699   pcbddc->vec2_R                     = 0;
700   pcbddc->local_auxmat1              = 0;
701   pcbddc->local_auxmat2              = 0;
702   pcbddc->R_to_B                     = 0;
703   pcbddc->R_to_D                     = 0;
704   pcbddc->ksp_D                      = 0;
705   pcbddc->ksp_R                      = 0;
706   pcbddc->local_primal_indices       = 0;
707   pcbddc->prec_type                  = PETSC_FALSE;
708   pcbddc->NeumannBoundaries          = 0;
709   pcbddc->ISForDofs                  = 0;
710   pcbddc->ISForVertices              = 0;
711   pcbddc->n_ISForFaces               = 0;
712   pcbddc->n_ISForEdges               = 0;
713   pcbddc->ConstraintMatrix           = 0;
714   pcbddc->use_nnsp_true              = PETSC_FALSE;
715   pcbddc->local_primal_sizes         = 0;
716   pcbddc->local_primal_displacements = 0;
717   pcbddc->replicated_local_primal_indices = 0;
718   pcbddc->replicated_local_primal_values  = 0;
719   pcbddc->coarse_loc_to_glob         = 0;
720   pcbddc->dbg_flag                   = PETSC_FALSE;
721   pcbddc->coarsening_ratio           = 8;
722   /* function pointers */
723   pc->ops->apply               = PCApply_BDDC;
724   pc->ops->applytranspose      = 0;
725   pc->ops->setup               = PCSetUp_BDDC;
726   pc->ops->destroy             = PCDestroy_BDDC;
727   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
728   pc->ops->view                = 0;
729   pc->ops->applyrichardson     = 0;
730   pc->ops->applysymmetricleft  = 0;
731   pc->ops->applysymmetricright = 0;
732   /* composing function */
733   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
734                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
735   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
736                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
737   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
738                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
739   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
740                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
741   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
742                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
743   PetscFunctionReturn(0);
744 }
745 EXTERN_C_END
746 
747 /* -------------------------------------------------------------------------- */
748 /*
749    Create C matrix [I 0; 0 const]
750 */
751 /* for testing only */
752 #if defined(PETSC_MISSING_LAPACK_GESVD)
753 #define BDDC_USE_POD
754 #define PETSC_MISSING_LAPACK_GESVD 1
755 #endif
756 
757 #undef __FUNCT__
758 #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
759 static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
760 {
761   PetscErrorCode ierr;
762   PC_IS*         pcis = (PC_IS*)(pc->data);
763   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
764   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
765   PetscInt       *nnz,*vertices,*is_indices;
766   PetscScalar    *temp_quadrature_constraint;
767   PetscInt       *temp_indices,*temp_indices_to_constraint;
768   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
769   PetscInt       n_constraints,n_vertices,size_of_constraint;
770   PetscReal      quad_value;
771   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
772   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
773   IS             *used_IS;
774   const MatType  impMatType=MATSEQAIJ;
775   PetscBLASInt   Bs,Bt,lwork,lierr;
776   PetscReal      tol=1.0e-8;
777   Vec            *localnearnullsp;
778   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
779   PetscReal      *rwork,*singular_vals;
780 /* some conditional variables */
781 #if defined(PETSC_MISSING_LAPACK_GESVD)
782   PetscScalar dot_result;
783   PetscScalar  one=1.0,zero=0.0;
784   PetscInt ii;
785 #if defined(PETSC_USE_COMPLEX)
786   PetscScalar val1,val2;
787 #else
788   PetscBLASInt Bone=1;
789 #endif
790 #else
791   PetscBLASInt dummy_int;
792   PetscScalar dummy_scalar;
793 #endif
794 
795 
796   PetscFunctionBegin;
797   /* check if near null space is attached to global mat */
798   if(pc->pmat->nearnullsp) {
799     nnsp_has_cnst = pc->pmat->nearnullsp->has_cnst;
800     nnsp_size = pc->pmat->nearnullsp->n;
801   } else { /* if near null space is not provided it uses constants */
802     nnsp_has_cnst = PETSC_TRUE;
803     use_nnsp_true = PETSC_TRUE;
804   }
805   if(nnsp_has_cnst) {
806     nnsp_addone = 1;
807   }
808   /*
809        Evaluate maximum storage size needed by the procedure
810        - temp_indices will contain start index of each constraint stored as follows
811        - temp_indices_to_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in local numbering) on which the constraint acts
812        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
813                                                                                                                                                          */
814   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
815   total_counts *= (nnsp_addone+nnsp_size);
816   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
817   total_counts = 0;
818   max_size_of_constraint = 0;
819   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
820     if(i<pcbddc->n_ISForEdges){
821       used_IS = &pcbddc->ISForEdges[i];
822     } else {
823       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
824     }
825     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
826     total_counts += j;
827     if(j>max_size_of_constraint) max_size_of_constraint=j;
828   }
829   total_counts *= (nnsp_addone+nnsp_size);
830   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
831   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
832   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
833   rwork = 0;
834   work = 0;
835   singular_vals = 0;
836   temp_basis = 0;
837   correlation_mat = 0;
838   if(!pcbddc->use_nnsp_true) {
839     PetscScalar temp_work;
840 #if defined(PETSC_MISSING_LAPACK_GESVD)
841     /* POD */
842     PetscInt max_n;
843     max_n = nnsp_addone+nnsp_size;
844     /* using some techniques borrowed from Proper Orthogonal Decomposition */
845     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
846     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
847     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
848 #if defined(PETSC_USE_COMPLEX)
849     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
850 #endif
851     /* now we evaluate the optimal workspace using query with lwork=-1 */
852     Bt = PetscBLASIntCast(max_n);
853     lwork=-1;
854 #if !defined(PETSC_USE_COMPLEX)
855     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
856 #else
857     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
858 #endif
859 #else /* on missing GESVD */
860     /* SVD */
861     PetscInt max_n,min_n;
862     max_n = max_size_of_constraint;
863     min_n = nnsp_addone+nnsp_size;
864     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
865       min_n = max_size_of_constraint;
866       max_n = nnsp_addone+nnsp_size;
867     }
868     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
869 #if defined(PETSC_USE_COMPLEX)
870     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
871 #endif
872     /* now we evaluate the optimal workspace using query with lwork=-1 */
873     lwork=-1;
874     Bs = PetscBLASIntCast(max_n);
875     Bt = PetscBLASIntCast(min_n);
876     dummy_int = Bs;
877 #if !defined(PETSC_USE_COMPLEX)
878     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
879                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
880 #else
881     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
882                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
883 #endif
884     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
885 #endif
886     /* Allocate optimal workspace */
887     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
888     total_counts = (PetscInt)lwork;
889     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
890   }
891   /* get local part of global near null space vectors */
892   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
893   for(k=0;k<nnsp_size;k++) {
894     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
895     ierr = VecScatterBegin(matis->ctx,pc->pmat->nearnullsp->vecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
896     ierr = VecScatterEnd  (matis->ctx,pc->pmat->nearnullsp->vecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
897   }
898   /* Now we can loop on constraining sets */
899   total_counts=0;
900   temp_indices[0]=0;
901   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
902     if(i<pcbddc->n_ISForEdges){
903       used_IS = &pcbddc->ISForEdges[i];
904     } else {
905       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
906     }
907     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
908     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
909     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
910     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
911     if(nnsp_has_cnst) {
912       temp_constraints++;
913       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
914       for(j=0;j<size_of_constraint;j++) {
915         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
916         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
917       }
918       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
919       total_counts++;
920     }
921     for(k=0;k<nnsp_size;k++) {
922       temp_constraints++;
923       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
924       for(j=0;j<size_of_constraint;j++) {
925         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
926         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
927       }
928       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
929       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
930       total_counts++;
931     }
932     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
933     /* perform SVD on the constraint if use true has not be requested by the user */
934     if(!use_nnsp_true) {
935       Bs = PetscBLASIntCast(size_of_constraint);
936       Bt = PetscBLASIntCast(temp_constraints);
937 #if defined(PETSC_MISSING_LAPACK_GESVD)
938       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
939       /* Store upper triangular part of correlation matrix */
940       for(j=0;j<temp_constraints;j++) {
941         for(k=0;k<j+1;k++) {
942 #if defined(PETSC_USE_COMPLEX)
943           /* hand made complex dot product */
944           dot_result = 0.0;
945           for (ii=0; ii<size_of_constraint; ii++) {
946             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
947             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
948             dot_result += val1*PetscConj(val2);
949           }
950 #else
951           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
952                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
953 #endif
954           correlation_mat[j*temp_constraints+k]=dot_result;
955         }
956       }
957 #if !defined(PETSC_USE_COMPLEX)
958       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
959 #else
960       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
961 #endif
962       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
963       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
964       j=0;
965       while( j < Bt && singular_vals[j] < tol) j++;
966       total_counts=total_counts-j;
967       if(j<temp_constraints) {
968         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
969         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
970         /* copy POD basis into used quadrature memory */
971         for(k=0;k<Bt-j;k++) {
972           for(ii=0;ii<size_of_constraint;ii++) {
973             temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[Bt-1-k]*temp_basis[(Bt-1-k)*size_of_constraint+ii];
974           }
975         }
976       }
977 #else  /* on missing GESVD */
978       PetscInt min_n = temp_constraints;
979       if(min_n > size_of_constraint) min_n = size_of_constraint;
980       dummy_int = Bs;
981 #if !defined(PETSC_USE_COMPLEX)
982       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
983                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
984 #else
985       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
986                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
987 #endif
988       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
989       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
990       j=0;
991       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
992       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
993 #endif
994     }
995   }
996   n_constraints=total_counts;
997   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
998   local_primal_size = n_vertices+n_constraints;
999   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1000   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1001   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
1002   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
1003   for(i=0;i<n_vertices;i++) { nnz[i]= 1; }
1004   for(i=0;i<n_constraints;i++) { nnz[i+n_vertices]=temp_indices[i+1]-temp_indices[i]; }
1005   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
1006   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1007   for(i=0;i<n_vertices;i++) { ierr = MatSetValue(pcbddc->ConstraintMatrix,i,vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr); }
1008   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1009   for(i=0;i<n_constraints;i++) {
1010     j=i+n_vertices;
1011     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1012     ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&j,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
1013   }
1014   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1015   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1016   /* set quantities in pcbddc data structure */
1017   pcbddc->n_vertices = n_vertices;
1018   pcbddc->n_constraints = n_constraints;
1019   pcbddc->local_primal_size = n_vertices+n_constraints;
1020   /* free workspace no longer needed */
1021   ierr = PetscFree(rwork);CHKERRQ(ierr);
1022   ierr = PetscFree(work);CHKERRQ(ierr);
1023   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
1024   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
1025   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
1026   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
1027   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
1028   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
1029   ierr = PetscFree(nnz);CHKERRQ(ierr);
1030   for(k=0;k<nnsp_size;k++) { ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr); }
1031   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
1032   PetscFunctionReturn(0);
1033 }
1034 #ifdef BDDC_USE_POD
1035 #undef PETSC_MISSING_LAPACK_GESVD
1036 #endif
1037 /* -------------------------------------------------------------------------- */
1038 /*
1039    PCBDDCCoarseSetUp -
1040 */
1041 #undef __FUNCT__
1042 #define __FUNCT__ "PCBDDCCoarseSetUp"
1043 static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
1044 {
1045   PetscErrorCode  ierr;
1046 
1047   PC_IS*            pcis = (PC_IS*)(pc->data);
1048   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1049   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1050   IS                is_R_local;
1051   IS                is_V_local;
1052   IS                is_C_local;
1053   IS                is_aux1;
1054   IS                is_aux2;
1055   const VecType     impVecType;
1056   const MatType     impMatType;
1057   PetscInt          n_R=0;
1058   PetscInt          n_D=0;
1059   PetscInt          n_B=0;
1060   PetscScalar       zero=0.0;
1061   PetscScalar       one=1.0;
1062   PetscScalar       m_one=-1.0;
1063   PetscScalar*      array;
1064   PetscScalar       *coarse_submat_vals;
1065   PetscInt          *idx_R_local;
1066   PetscInt          *idx_V_B;
1067   PetscScalar       *coarsefunctions_errors;
1068   PetscScalar       *constraints_errors;
1069   /* auxiliary indices */
1070   PetscInt s,i,j,k;
1071   /* for verbose output of bddc */
1072   PetscViewer       viewer=pcbddc->dbg_viewer;
1073   PetscBool         dbg_flag=pcbddc->dbg_flag;
1074   /* for counting coarse dofs */
1075   PetscScalar       coarsesum;
1076   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
1077   PetscInt          size_of_constraint;
1078   PetscInt          *row_cmat_indices;
1079   PetscScalar       *row_cmat_values;
1080   const PetscInt    *vertices;
1081 
1082   PetscFunctionBegin;
1083   /* Set Non-overlapping dimensions */
1084   n_B = pcis->n_B; n_D = pcis->n - n_B;
1085   ierr = ISGetIndices(pcbddc->ISForVertices,&vertices);CHKERRQ(ierr);
1086   /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants) */
1087   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1088   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1089   for(i=0;i<n_vertices;i++) { array[ vertices[i] ] = one; }
1090 
1091   for(i=0;i<n_constraints;i++) {
1092     ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1093     for (j=0; j<size_of_constraint; j++) {
1094       k = row_cmat_indices[j];
1095       if( array[k] == zero ) {
1096         array[k] = one;
1097         break;
1098       }
1099     }
1100     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1101   }
1102   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1103   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1104   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1105   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1106   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1107   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1108   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1109   for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1110   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1111   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1112   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1113   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1114   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1115   pcbddc->coarse_size = (PetscInt) coarsesum;
1116 
1117   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
1118   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
1119   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1120   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
1121   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
1122   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
1123   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1124   if(dbg_flag) {
1125     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1126     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1127     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1128     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
1129     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr);
1130     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1131     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1132     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1133     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1134   }
1135   /* Allocate needed vectors */
1136   /* Set Mat type for local matrices needed by BDDC precondtioner */
1137   impMatType = MATSEQDENSE;
1138   impVecType = VECSEQ;
1139   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
1140   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
1141   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
1142   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
1143   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1144   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1145   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
1146   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
1147   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1148 
1149   /* Creating some index sets needed  */
1150   /* For submatrices */
1151   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
1152   if(n_vertices)    {
1153     ierr = ISDuplicate(pcbddc->ISForVertices,&is_V_local);CHKERRQ(ierr);
1154     ierr = ISCopy(pcbddc->ISForVertices,is_V_local);CHKERRQ(ierr);
1155   }
1156   if(n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr); }
1157   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
1158   {
1159     PetscInt   *aux_array1;
1160     PetscInt   *aux_array2;
1161     PetscScalar      value;
1162 
1163     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
1164     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
1165 
1166     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1167     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1168     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1169     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1170     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1171     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1172     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1173     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1174     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
1175     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1176     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
1177     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1178     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
1179     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1180     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
1181     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1182     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
1183     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
1184     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1185     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1186 
1187     if(pcbddc->prec_type || dbg_flag ) {
1188       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
1189       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1190       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
1191       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1192       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
1193       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1194       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
1195       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1196     }
1197 
1198     /* Check scatters */
1199     if(dbg_flag) {
1200 
1201       Vec            vec_aux;
1202 
1203       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1204       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
1205       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1206       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1207       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1208       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1209       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1210       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1211       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1212       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1213       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1214       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1215       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
1216       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1217       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
1218 
1219       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1220       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1221       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
1222       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
1223       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1224       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1225       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1226       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1227       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
1228       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
1229       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1230       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
1231 
1232       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1233       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
1234       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1235 
1236       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1237       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1238       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1239       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1240       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1241       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1242       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1243       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1244       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1245       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
1246       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1247       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
1248 
1249       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1250       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1251       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
1252       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
1253       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1254       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1255       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1256       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1257       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
1258       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
1259       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1260       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
1261       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1262 
1263     }
1264   }
1265 
1266   /* vertices in boundary numbering */
1267   if(n_vertices) {
1268     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
1269     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1270     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
1271     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1272     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1273     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1274     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1275     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1276     for (i=0; i<n_vertices; i++) {
1277       s=0;
1278       while (array[s] != i ) {s++;}
1279       idx_V_B[i]=s;
1280     }
1281     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1282   }
1283 
1284 
1285   /* Creating PC contexts for local Dirichlet and Neumann problems */
1286   {
1287     Mat  A_RR;
1288     PC   pc_temp;
1289     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
1290     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1291     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1292     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
1293     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1294     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
1295     /* default */
1296     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1297     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
1298     /* Allow user's customization */
1299     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1300     /* Set Up KSP for Dirichlet problem of BDDC */
1301     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1302     /* Matrix for Neumann problem is A_RR -> we need to create it */
1303     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
1304     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1305     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1306     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
1307     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1308     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
1309     /* default */
1310     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1311     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
1312     /* Allow user's customization */
1313     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1314     /* Set Up KSP for Neumann problem of BDDC */
1315     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1316     /* check Dirichlet and Neumann solvers */
1317     if(pcbddc->dbg_flag) {
1318       Vec temp_vec;
1319       PetscScalar value;
1320 
1321       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1322       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1323       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1324       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1325       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1326       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1327       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1328       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1329       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1330       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1331       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1332       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1333       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1334       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1335       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1336       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1337       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1338       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1339       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1340       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1341     }
1342     /* free Neumann problem's matrix */
1343     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1344   }
1345 
1346   /* Assemble all remaining stuff needed to apply BDDC  */
1347   {
1348     Mat          A_RV,A_VR,A_VV;
1349     Mat          M1,M2;
1350     Mat          C_CR;
1351     Mat          AUXMAT;
1352     Vec          vec1_C;
1353     Vec          vec2_C;
1354     Vec          vec1_V;
1355     Vec          vec2_V;
1356     PetscInt     *nnz;
1357     PetscInt     *auxindices;
1358     PetscInt     index;
1359     PetscScalar* array2;
1360     MatFactorInfo matinfo;
1361 
1362     /* Allocating some extra storage just to be safe */
1363     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1364     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
1365     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
1366 
1367     /* some work vectors on vertices and/or constraints */
1368     if(n_vertices) {
1369       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
1370       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
1371       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
1372       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
1373     }
1374     if(pcbddc->n_constraints) {
1375       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
1376       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
1377       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
1378       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
1379       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
1380     }
1381     /* Precompute stuffs needed for preprocessing and application of BDDC*/
1382     if(n_constraints) {
1383       /* some work vectors */
1384       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1385       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
1386       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
1387       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
1388 
1389       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
1390       for(i=0;i<n_constraints;i++) {
1391         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1392         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1393         /* Get row of constraint matrix in R numbering */
1394         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1395         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
1396         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
1397         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
1398         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1399         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
1400         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1401         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1402         /* Solve for row of constraint matrix in R numbering */
1403         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1404         /* Set values */
1405         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1406         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1407         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1408       }
1409       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1410       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1411 
1412       /* Create Constraint matrix on R nodes: C_{CR}  */
1413       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
1414       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
1415 
1416       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
1417       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1418       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
1419       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
1420       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
1421       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1422 
1423       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1424       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
1425       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
1426       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
1427       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
1428       for(i=0;i<n_constraints;i++) {
1429         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
1430         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
1431         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
1432         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
1433         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
1434         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
1435         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
1436         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1437         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
1438       }
1439       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1440       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1441       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1442       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
1443       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
1444 
1445     }
1446 
1447     /* Get submatrices from subdomain matrix */
1448     if(n_vertices){
1449       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1450       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1451       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1452       /* Assemble M2 = A_RR^{-1}A_RV */
1453       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
1454       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
1455       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
1456       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
1457       for(i=0;i<n_vertices;i++) {
1458         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
1459         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
1460         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
1461         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
1462         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
1463         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1464         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1465         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1466         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1467       }
1468       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1469       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1470     }
1471 
1472     /* Matrix of coarse basis functions (local) */
1473     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1474     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
1475     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
1476     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1477     if(pcbddc->prec_type || dbg_flag ) {
1478       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1479       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
1480       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
1481       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
1482     }
1483 
1484     if(dbg_flag) {
1485       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
1486       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
1487     }
1488     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1489     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
1490 
1491     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
1492     for(i=0;i<n_vertices;i++){
1493       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
1494       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
1495       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
1496       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
1497       /* solution of saddle point problem */
1498       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
1499       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
1500       if(n_constraints) {
1501         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
1502         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
1503         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
1504       }
1505       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
1506       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
1507 
1508       /* Set values in coarse basis function and subdomain part of coarse_mat */
1509       /* coarse basis functions */
1510       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1511       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1512       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1513       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1514       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1515       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1516       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1517       if( pcbddc->prec_type || dbg_flag  ) {
1518         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1519         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1520         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1521         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1522         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1523       }
1524       /* subdomain contribution to coarse matrix */
1525       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1526       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } //WARNING -> column major ordering
1527       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1528       if(n_constraints) {
1529         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1530         for(j=0;j<n_constraints;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j+n_vertices] = array[j]; } //WARNING -> column major ordering
1531         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1532       }
1533 
1534       if( dbg_flag ) {
1535         /* assemble subdomain vector on nodes */
1536         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1537         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1538         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1539         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
1540         array[ vertices[i] ] = one;
1541         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1542         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1543         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1544         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
1545         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1546         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1547         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
1548         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1549         if(n_constraints) {
1550           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1551           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
1552           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1553         }
1554         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1555         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
1556         /* check saddle point solution */
1557         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1558         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
1559         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
1560         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
1561         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1562         array[i]=array[i]+m_one;  /* shift by the identity matrix */
1563         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1564         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
1565       }
1566     }
1567 
1568     for(i=0;i<n_constraints;i++){
1569       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
1570       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
1571       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
1572       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
1573       /* solution of saddle point problem */
1574       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
1575       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
1576       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
1577       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
1578       /* Set values in coarse basis function and subdomain part of coarse_mat */
1579       /* coarse basis functions */
1580       index=i+n_vertices;
1581       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1582       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1583       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1584       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1585       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
1586       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1587       if( pcbddc->prec_type || dbg_flag ) {
1588         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1589         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1590         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1591         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
1592         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1593       }
1594       /* subdomain contribution to coarse matrix */
1595       if(n_vertices) {
1596         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1597         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
1598         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1599       }
1600       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1601       for(j=0;j<n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+n_vertices]=array[j];} //WARNING -> column major ordering
1602       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1603 
1604       if( dbg_flag ) {
1605         /* assemble subdomain vector on nodes */
1606         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1607         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1608         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1609         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
1610         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1611         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1612         /* assemble subdomain vector of lagrange multipliers */
1613         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
1614         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1615         if( n_vertices) {
1616           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1617           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
1618           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1619         }
1620         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1621         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
1622         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1623         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1624         /* check saddle point solution */
1625         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1626         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
1627         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
1628         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
1629         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1630         array[index]=array[index]+m_one; /* shift by the identity matrix */
1631         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1632         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
1633       }
1634     }
1635     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1636     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1637     if( pcbddc->prec_type || dbg_flag ) {
1638       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1639       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1640     }
1641     /* Checking coarse_sub_mat and coarse basis functios */
1642     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1643     if(dbg_flag) {
1644 
1645       Mat coarse_sub_mat;
1646       Mat TM1,TM2,TM3,TM4;
1647       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1648       const MatType checkmattype=MATSEQAIJ;
1649       PetscScalar      value;
1650 
1651       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1652       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1653       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1654       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1655       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1656       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1657       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1658       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
1659 
1660       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1661       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
1662       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1663       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
1664       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
1665       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1666       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
1667       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1668       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1669       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
1670       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1671       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1672       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1673       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1674       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1675       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
1676       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
1677       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
1678       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
1679       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
1680       for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr); }
1681       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
1682       for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr); }
1683       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1684       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
1685       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
1686       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
1687       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
1688       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
1689       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
1690       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
1691       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
1692       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
1693       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
1694       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1695       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
1696       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
1697     }
1698 
1699     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
1700     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
1701     /* free memory */
1702     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1703     ierr = PetscFree(auxindices);CHKERRQ(ierr);
1704     ierr = PetscFree(nnz);CHKERRQ(ierr);
1705     if(n_vertices) {
1706       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
1707       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
1708       ierr = MatDestroy(&M2);CHKERRQ(ierr);
1709       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1710       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1711       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1712     }
1713     if(pcbddc->n_constraints) {
1714       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
1715       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
1716       ierr = MatDestroy(&M1);CHKERRQ(ierr);
1717       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1718     }
1719   }
1720   /* free memory */
1721   if(n_vertices) {
1722     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
1723     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
1724   }
1725   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1726   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1727   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1728 
1729   PetscFunctionReturn(0);
1730 }
1731 
1732 /* -------------------------------------------------------------------------- */
1733 
1734 #undef __FUNCT__
1735 #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
1736 static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
1737 {
1738 
1739 
1740   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
1741   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
1742   PC_IS     *pcis     = (PC_IS*)pc->data;
1743   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
1744   MPI_Comm  coarse_comm;
1745 
1746   /* common to all choiches */
1747   PetscScalar *temp_coarse_mat_vals;
1748   PetscScalar *ins_coarse_mat_vals;
1749   PetscInt    *ins_local_primal_indices;
1750   PetscMPIInt *localsizes2,*localdispl2;
1751   PetscMPIInt size_prec_comm;
1752   PetscMPIInt rank_prec_comm;
1753   PetscMPIInt active_rank=MPI_PROC_NULL;
1754   PetscMPIInt master_proc=0;
1755   PetscInt    ins_local_primal_size;
1756   /* specific to MULTILEVEL_BDDC */
1757   PetscMPIInt *ranks_recv;
1758   PetscMPIInt count_recv=0;
1759   PetscMPIInt rank_coarse_proc_send_to;
1760   PetscMPIInt coarse_color = MPI_UNDEFINED;
1761   ISLocalToGlobalMapping coarse_ISLG;
1762   /* some other variables */
1763   PetscErrorCode ierr;
1764   const MatType coarse_mat_type;
1765   const PCType  coarse_pc_type;
1766   const KSPType  coarse_ksp_type;
1767   PC pc_temp;
1768   PetscInt i,j,k,bs;
1769   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1770   /* verbose output viewer */
1771   PetscViewer viewer=pcbddc->dbg_viewer;
1772   PetscBool   dbg_flag=pcbddc->dbg_flag;
1773 
1774   PetscFunctionBegin;
1775 
1776   ins_local_primal_indices = 0;
1777   ins_coarse_mat_vals      = 0;
1778   localsizes2              = 0;
1779   localdispl2              = 0;
1780   temp_coarse_mat_vals     = 0;
1781   coarse_ISLG              = 0;
1782 
1783   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
1784   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
1785   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1786 
1787   /* Assign global numbering to coarse dofs */
1788   {
1789     PetscScalar    one=1.,zero=0.;
1790     PetscScalar    *array;
1791     PetscMPIInt    *auxlocal_primal;
1792     PetscMPIInt    *auxglobal_primal;
1793     PetscMPIInt    *all_auxglobal_primal;
1794     PetscMPIInt    *all_auxglobal_primal_dummy;
1795     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1796     PetscInt       *vertices,*row_cmat_indices;
1797     PetscInt       size_of_constraint;
1798 
1799     /* Construct needed data structures for message passing */
1800     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1801     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1802     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1803     /* Gather local_primal_size information for all processes  */
1804     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1805     pcbddc->replicated_primal_size = 0;
1806     for (i=0; i<size_prec_comm; i++) {
1807       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1808       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1809     }
1810     if(rank_prec_comm == 0) {
1811       /* allocate some auxiliary space */
1812       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1813       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1814     }
1815     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1816     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1817 
1818     /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants)
1819        This code fragment assumes that the number of local constraints per connected component
1820        is not greater than the number of nodes defined for the connected component
1821        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1822     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1823     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1824     ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1825     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1826     for(i=0;i<pcbddc->n_vertices;i++) {  /* note that  pcbddc->n_vertices can be different from size of ISForVertices */
1827       array[ vertices[i] ] = one;
1828       auxlocal_primal[i] = vertices[i];
1829     }
1830     ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1831     for(i=0;i<pcbddc->n_constraints;i++) {
1832       ierr = MatGetRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1833       for (j=0; j<size_of_constraint; j++) {
1834         k = row_cmat_indices[j];
1835         if( array[k] == zero ) {
1836           array[k] = one;
1837           auxlocal_primal[i+pcbddc->n_vertices] = k;
1838           break;
1839         }
1840       }
1841       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1842     }
1843     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1844 
1845     /* Now assign them a global numbering */
1846     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1847     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1848     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1849     ierr = MPI_Gatherv(&auxglobal_primal[0],pcbddc->local_primal_size,MPIU_INT,&all_auxglobal_primal[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1850 
1851     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1852     /* It implements a function similar to PetscSortRemoveDupsInt */
1853     if(rank_prec_comm==0) {
1854       /* dummy argument since PetscSortMPIInt doesn't exist! */
1855       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1856       k=1;
1857       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1858       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1859         if(j != all_auxglobal_primal[i] ) {
1860           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1861           k++;
1862           j=all_auxglobal_primal[i];
1863         }
1864       }
1865     } else {
1866       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1867     }
1868     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1869     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1870 
1871     /* Now get global coarse numbering of local primal nodes */
1872     for(i=0;i<pcbddc->local_primal_size;i++) {
1873       k=0;
1874       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1875       pcbddc->local_primal_indices[i]=k;
1876     }
1877     if(dbg_flag) {
1878       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1879       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1880       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1881       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1882       for(i=0;i<pcbddc->local_primal_size;i++) {
1883         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1884       }
1885       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1886     }
1887     /* free allocated memory */
1888     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1889     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1890     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1891     if(rank_prec_comm == 0) {
1892       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1893     }
1894   }
1895 
1896   /* adapt coarse problem type */
1897   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
1898     pcbddc->coarse_problem_type = PARALLEL_BDDC;
1899 
1900   switch(pcbddc->coarse_problem_type){
1901 
1902     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
1903     {
1904       /* we need additional variables */
1905       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
1906       MetisInt   *metis_coarse_subdivision;
1907       MetisInt   options[METIS_NOPTIONS];
1908       PetscMPIInt size_coarse_comm,rank_coarse_comm;
1909       PetscMPIInt procs_jumps_coarse_comm;
1910       PetscMPIInt *coarse_subdivision;
1911       PetscMPIInt *total_count_recv;
1912       PetscMPIInt *total_ranks_recv;
1913       PetscMPIInt *displacements_recv;
1914       PetscMPIInt *my_faces_connectivity;
1915       PetscMPIInt *petsc_faces_adjncy;
1916       MetisInt    *faces_adjncy;
1917       MetisInt    *faces_xadj;
1918       PetscMPIInt *number_of_faces;
1919       PetscMPIInt *faces_displacements;
1920       PetscInt    *array_int;
1921       PetscMPIInt my_faces=0;
1922       PetscMPIInt total_faces=0;
1923       PetscInt    ranks_stretching_ratio;
1924 
1925       /* define some quantities */
1926       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1927       coarse_mat_type = MATIS;
1928       coarse_pc_type  = PCBDDC;
1929       coarse_ksp_type  = KSPCHEBYCHEV;
1930 
1931       /* details of coarse decomposition */
1932       n_subdomains = pcbddc->active_procs;
1933       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1934       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
1935       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
1936 
1937       printf("Coarse algorithm details: \n");
1938       printf("n_subdomains %d, n_parts %d\nstretch %d,jumps %d,coarse_ratio %d\nlevel should be log_%d(%d)\n",n_subdomains,n_parts,ranks_stretching_ratio,procs_jumps_coarse_comm,pcbddc->coarsening_ratio,pcbddc->coarsening_ratio,(ranks_stretching_ratio/pcbddc->coarsening_ratio+1));
1939 
1940       /* build CSR graph of subdomains' connectivity through faces */
1941       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
1942       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
1943       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
1944         for(j=0;j<pcis->n_shared[i];j++){
1945           array_int[ pcis->shared[i][j] ]+=1;
1946         }
1947       }
1948       for(i=1;i<pcis->n_neigh;i++){
1949         for(j=0;j<pcis->n_shared[i];j++){
1950           if(array_int[ pcis->shared[i][j] ] == 1 ){
1951             my_faces++;
1952             break;
1953           }
1954         }
1955       }
1956       //printf("I found %d faces.\n",my_faces);
1957 
1958       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
1959       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
1960       my_faces=0;
1961       for(i=1;i<pcis->n_neigh;i++){
1962         for(j=0;j<pcis->n_shared[i];j++){
1963           if(array_int[ pcis->shared[i][j] ] == 1 ){
1964             my_faces_connectivity[my_faces]=pcis->neigh[i];
1965             my_faces++;
1966             break;
1967           }
1968         }
1969       }
1970       if(rank_prec_comm == master_proc) {
1971         //printf("I found %d total faces.\n",total_faces);
1972         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
1973         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
1974         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
1975         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
1976         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
1977       }
1978       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
1979       if(rank_prec_comm == master_proc) {
1980         faces_xadj[0]=0;
1981         faces_displacements[0]=0;
1982         j=0;
1983         for(i=1;i<size_prec_comm+1;i++) {
1984           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
1985           if(number_of_faces[i-1]) {
1986             j++;
1987             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
1988           }
1989         }
1990         printf("The J I count is %d and should be %d\n",j,n_subdomains);
1991         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
1992       }
1993       ierr = MPI_Gatherv(&my_faces_connectivity[0],my_faces,MPIU_INT,&petsc_faces_adjncy[0],number_of_faces,faces_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
1994       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
1995       ierr = PetscFree(array_int);CHKERRQ(ierr);
1996       if(rank_prec_comm == master_proc) {
1997         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
1998         printf("This is the face connectivity (actual ranks)\n");
1999         for(i=0;i<n_subdomains;i++){
2000           printf("proc %d is connected with \n",i);
2001           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
2002             printf("%d ",faces_adjncy[j]);
2003           printf("\n");
2004         }
2005         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
2006         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
2007         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
2008       }
2009 
2010       if( rank_prec_comm == master_proc ) {
2011 
2012         PetscInt heuristic_for_metis=3;
2013 
2014         ncon=1;
2015         faces_nvtxs=n_subdomains;
2016         /* partition graoh induced by face connectivity */
2017         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
2018         ierr = METIS_SetDefaultOptions(options);
2019         /* we need a contiguous partition of the coarse mesh */
2020         options[METIS_OPTION_CONTIG]=1;
2021         options[METIS_OPTION_DBGLVL]=1;
2022         options[METIS_OPTION_NITER]=30;
2023         //options[METIS_OPTION_NCUTS]=1;
2024         printf("METIS PART GRAPH\n");
2025         if(n_subdomains>n_parts*heuristic_for_metis) {
2026           printf("Using Kway\n");
2027           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
2028           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
2029           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2030         } else {
2031           printf("Using Recursive\n");
2032           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2033         }
2034         if(ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetupCoarseEnvironment\n",ierr);
2035         printf("Partition done!\n");
2036         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
2037         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
2038         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
2039         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
2040         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
2041         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
2042         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
2043       }
2044 
2045       /* Create new communicator for coarse problem splitting the old one */
2046       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2047         coarse_color=0;              //for communicator splitting
2048         active_rank=rank_prec_comm;  //for insertion of matrix values
2049       }
2050       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2051       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
2052       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
2053 
2054       if( coarse_color == 0 ) {
2055         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
2056         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2057         printf("Details of coarse comm\n");
2058         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
2059         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
2060       } else {
2061         rank_coarse_comm = MPI_PROC_NULL;
2062       }
2063 
2064       /* master proc take care of arranging and distributing coarse informations */
2065       if(rank_coarse_comm == master_proc) {
2066         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
2067         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
2068         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
2069         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
2070         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
2071         /* some initializations */
2072         displacements_recv[0]=0;
2073         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
2074         /* count from how many processes the j-th process of the coarse decomposition will receive data */
2075         for(j=0;j<size_coarse_comm;j++)
2076           for(i=0;i<size_prec_comm;i++)
2077             if(coarse_subdivision[i]==j)
2078               total_count_recv[j]++;
2079         /* displacements needed for scatterv of total_ranks_recv */
2080         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
2081         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
2082         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
2083         for(j=0;j<size_coarse_comm;j++) {
2084           for(i=0;i<size_prec_comm;i++) {
2085             if(coarse_subdivision[i]==j) {
2086               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
2087               total_count_recv[j]+=1;
2088             }
2089           }
2090         }
2091         for(j=0;j<size_coarse_comm;j++) {
2092           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
2093           for(i=0;i<total_count_recv[j];i++) {
2094             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
2095           }
2096           printf("\n");
2097         }
2098 
2099         /* identify new decomposition in terms of ranks in the old communicator */
2100         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
2101         printf("coarse_subdivision in old end new ranks\n");
2102         for(i=0;i<size_prec_comm;i++)
2103           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
2104             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
2105           } else {
2106             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
2107           }
2108         printf("\n");
2109       }
2110 
2111       /* Scatter new decomposition for send details */
2112       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
2113       /* Scatter receiving details to members of coarse decomposition */
2114       if( coarse_color == 0) {
2115         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
2116         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
2117         ierr = MPI_Scatterv(&total_ranks_recv[0],total_count_recv,displacements_recv,MPIU_INT,&ranks_recv[0],count_recv,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
2118       }
2119 
2120       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2121       //if(coarse_color == 0) {
2122       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2123       //  for(i=0;i<count_recv;i++)
2124       //    printf("%d ",ranks_recv[i]);
2125       //  printf("\n");
2126       //}
2127 
2128       if(rank_prec_comm == master_proc) {
2129         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2130         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
2131         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
2132         free(coarse_subdivision);
2133         free(total_count_recv);
2134         free(total_ranks_recv);
2135         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
2136       }
2137       break;
2138     }
2139 
2140     case(REPLICATED_BDDC):
2141 
2142       pcbddc->coarse_communications_type = GATHERS_BDDC;
2143       coarse_mat_type = MATSEQAIJ;
2144       coarse_pc_type  = PCLU;
2145       coarse_ksp_type  = KSPPREONLY;
2146       coarse_comm = PETSC_COMM_SELF;
2147       active_rank = rank_prec_comm;
2148       break;
2149 
2150     case(PARALLEL_BDDC):
2151 
2152       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2153       coarse_mat_type = MATMPIAIJ;
2154       coarse_pc_type  = PCREDUNDANT;
2155       coarse_ksp_type  = KSPPREONLY;
2156       coarse_comm = prec_comm;
2157       active_rank = rank_prec_comm;
2158       break;
2159 
2160     case(SEQUENTIAL_BDDC):
2161       pcbddc->coarse_communications_type = GATHERS_BDDC;
2162       coarse_mat_type = MATSEQAIJ;
2163       coarse_pc_type = PCLU;
2164       coarse_ksp_type  = KSPPREONLY;
2165       coarse_comm = PETSC_COMM_SELF;
2166       active_rank = master_proc;
2167       break;
2168   }
2169 
2170   switch(pcbddc->coarse_communications_type){
2171 
2172     case(SCATTERS_BDDC):
2173       {
2174         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
2175 
2176           PetscMPIInt send_size;
2177           PetscInt    *aux_ins_indices;
2178           PetscInt    ii,jj;
2179           MPI_Request *requests;
2180 
2181           /* allocate auxiliary space */
2182           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
2183           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],pcbddc->local_primal_size,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
2184           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
2185           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
2186           /* allocate stuffs for message massing */
2187           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2188           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
2189           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
2190           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2191           /* fill up quantities */
2192           j=0;
2193           for(i=0;i<count_recv;i++){
2194             ii = ranks_recv[i];
2195             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
2196             localdispl2[i]=j;
2197             j+=localsizes2[i];
2198             jj = pcbddc->local_primal_displacements[ii];
2199             for(k=0;k<pcbddc->local_primal_sizes[ii];k++) aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]]+=1;  // it counts the coarse subdomains sharing the coarse node
2200           }
2201           //printf("aux_ins_indices 1\n");
2202           //for(i=0;i<pcbddc->coarse_size;i++)
2203           //  printf("%d ",aux_ins_indices[i]);
2204           //printf("\n");
2205           /* temp_coarse_mat_vals used to store temporarly received matrix values */
2206           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
2207           /* evaluate how many values I will insert in coarse mat */
2208           ins_local_primal_size=0;
2209           for(i=0;i<pcbddc->coarse_size;i++)
2210             if(aux_ins_indices[i])
2211               ins_local_primal_size++;
2212           /* evaluate indices I will insert in coarse mat */
2213           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2214           j=0;
2215           for(i=0;i<pcbddc->coarse_size;i++)
2216             if(aux_ins_indices[i])
2217               ins_local_primal_indices[j++]=i;
2218           /* use aux_ins_indices to realize a global to local mapping */
2219           j=0;
2220           for(i=0;i<pcbddc->coarse_size;i++){
2221             if(aux_ins_indices[i]==0){
2222               aux_ins_indices[i]=-1;
2223             } else {
2224               aux_ins_indices[i]=j;
2225               j++;
2226             }
2227           }
2228 
2229           //printf("New details localsizes2 localdispl2\n");
2230           //for(i=0;i<count_recv;i++)
2231           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
2232           //printf("\n");
2233           //printf("aux_ins_indices 2\n");
2234           //for(i=0;i<pcbddc->coarse_size;i++)
2235           //  printf("%d ",aux_ins_indices[i]);
2236           //printf("\n");
2237           //printf("ins_local_primal_indices\n");
2238           //for(i=0;i<ins_local_primal_size;i++)
2239           //  printf("%d ",ins_local_primal_indices[i]);
2240           //printf("\n");
2241           //printf("coarse_submat_vals\n");
2242           //for(i=0;i<pcbddc->local_primal_size;i++)
2243           //  for(j=0;j<pcbddc->local_primal_size;j++)
2244           //    printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]);
2245           //printf("\n");
2246 
2247           /* processes partecipating in coarse problem receive matrix data from their friends */
2248           for(i=0;i<count_recv;i++) ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2249           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2250             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
2251             ierr = MPI_Isend(&coarse_submat_vals[0],send_size,MPIU_SCALAR,rank_coarse_proc_send_to,666,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2252           }
2253           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2254 
2255           //if(coarse_color == 0) {
2256           //  printf("temp_coarse_mat_vals\n");
2257           //  for(k=0;k<count_recv;k++){
2258           //    printf("---- %d ----\n",ranks_recv[k]);
2259           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
2260           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
2261           //        printf("(%lf %d %d)\n",temp_coarse_mat_vals[localdispl2[k]+j*pcbddc->local_primal_sizes[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+j]);
2262           //    printf("\n");
2263           //  }
2264           //}
2265           /* calculate data to insert in coarse mat */
2266           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
2267           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
2268 
2269           PetscMPIInt rr,kk,lps,lpd;
2270           PetscInt row_ind,col_ind;
2271           for(k=0;k<count_recv;k++){
2272             rr = ranks_recv[k];
2273             kk = localdispl2[k];
2274             lps = pcbddc->local_primal_sizes[rr];
2275             lpd = pcbddc->local_primal_displacements[rr];
2276             //printf("Inserting the following indices (received from %d)\n",rr);
2277             for(j=0;j<lps;j++){
2278               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
2279               for(i=0;i<lps;i++){
2280                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
2281                 //printf("%d %d\n",row_ind,col_ind);
2282                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
2283               }
2284             }
2285           }
2286           ierr = PetscFree(requests);CHKERRQ(ierr);
2287           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
2288           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
2289           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2290 
2291           /* create local to global mapping needed by coarse MATIS */
2292           {
2293             IS coarse_IS;
2294             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
2295             coarse_comm = prec_comm;
2296             active_rank=rank_prec_comm;
2297             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
2298             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
2299             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
2300           }
2301         }
2302         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
2303           /* arrays for values insertion */
2304           ins_local_primal_size = pcbddc->local_primal_size;
2305           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
2306           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
2307           for(j=0;j<ins_local_primal_size;j++){
2308             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
2309             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
2310           }
2311         }
2312         break;
2313 
2314     }
2315 
2316     case(GATHERS_BDDC):
2317       {
2318 
2319         PetscMPIInt mysize,mysize2;
2320 
2321         if(rank_prec_comm==active_rank) {
2322           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
2323           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
2324           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
2325           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2326           /* arrays for values insertion */
2327           ins_local_primal_size = pcbddc->coarse_size;
2328           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
2329           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
2330           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
2331           localdispl2[0]=0;
2332           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
2333           j=0;
2334           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
2335           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
2336         }
2337 
2338         mysize=pcbddc->local_primal_size;
2339         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2340         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2341           ierr = MPI_Gatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
2342           ierr = MPI_Gatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,master_proc,prec_comm);CHKERRQ(ierr);
2343         } else {
2344           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
2345           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
2346         }
2347 
2348   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
2349         if(rank_prec_comm==active_rank) {
2350           PetscInt offset,offset2,row_ind,col_ind;
2351           for(j=0;j<ins_local_primal_size;j++){
2352             ins_local_primal_indices[j]=j;
2353             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
2354           }
2355           for(k=0;k<size_prec_comm;k++){
2356             offset=pcbddc->local_primal_displacements[k];
2357             offset2=localdispl2[k];
2358             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
2359               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
2360               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
2361                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
2362                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
2363               }
2364             }
2365           }
2366         }
2367         break;
2368       }//switch on coarse problem and communications associated with finished
2369   }
2370 
2371   /* Now create and fill up coarse matrix */
2372   if( rank_prec_comm == active_rank ) {
2373     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2374       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
2375       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
2376       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2377       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2378       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2379       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
2380     } else {
2381       Mat matis_coarse_local_mat;
2382       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
2383       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2384       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2385       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2386       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2387       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
2388     }
2389     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
2390     ierr = MatSetValues(pcbddc->coarse_mat,ins_local_primal_size,ins_local_primal_indices,ins_local_primal_size,ins_local_primal_indices,ins_coarse_mat_vals,ADD_VALUES);CHKERRQ(ierr);
2391     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2392     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2393     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2394       Mat matis_coarse_local_mat;
2395       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2396       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
2397     }
2398 
2399     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
2400     /* Preconditioner for coarse problem */
2401     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
2402     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
2403     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
2404     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
2405     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
2406     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
2407     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
2408     /* Allow user's customization */
2409     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
2410     /* Set Up PC for coarse problem BDDC */
2411     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2412       if(dbg_flag) {
2413         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2414         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2415       }
2416       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2417     }
2418     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2419     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2420       if(dbg_flag) {
2421         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
2422         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2423       }
2424     }
2425   }
2426   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
2427      IS local_IS,global_IS;
2428      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
2429      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
2430      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2431      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
2432      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
2433   }
2434 
2435 
2436   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
2437   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
2438     PetscScalar m_one=-1.0;
2439     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
2440     const KSPType check_ksp_type=KSPGMRES;
2441 
2442     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
2443     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2444     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
2445     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2446     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2447     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2448     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2449     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2450     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2451     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2452     if(dbg_flag) {
2453       kappa_2=lambda_max/lambda_min;
2454       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2455       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2456       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2457       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem condition number estimated with %d iterations of %s is: % 1.14e\n",k,check_ksp_type,kappa_2);CHKERRQ(ierr);
2458       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2459       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
2460     }
2461     /* restore coarse ksp to default values */
2462     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
2463     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
2464     ierr = KSPChebychevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
2465     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
2466     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
2467     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2468   }
2469 
2470   /* free data structures no longer needed */
2471   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2472   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
2473   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
2474   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
2475   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
2476   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
2477 
2478   PetscFunctionReturn(0);
2479 }
2480 
2481 #undef __FUNCT__
2482 #define __FUNCT__ "PCBDDCManageLocalBoundaries"
2483 static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
2484 {
2485 
2486   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2487   PC_IS         *pcis = (PC_IS*)pc->data;
2488   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
2489   PCBDDCGraph mat_graph;
2490   Mat         mat_adj;
2491   PetscInt    **neighbours_set;
2492   PetscInt    *queue_in_global_numbering;
2493   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
2494   PetscInt    total_counts,nodes_touched=0,where_values=1,vertex_size;
2495   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
2496   PetscBool   same_set,flg_row;
2497   PetscBool   symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2498   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
2499   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
2500   const PetscInt *neumann_nodes;
2501   const PetscInt *dirichlet_nodes;
2502 
2503   PetscFunctionBegin;
2504   /* allocate and initialize needed graph structure */
2505   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
2506   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2507   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2508   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
2509   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2510   i = mat_graph->nvtxs;
2511   ierr = PetscMalloc4(i,PetscInt,&mat_graph->where,i,PetscInt,&mat_graph->count,i+1,PetscInt,&mat_graph->cptr,i,PetscInt,&mat_graph->queue);CHKERRQ(ierr);
2512   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2513   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2514   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2515   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2516   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2517   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2518   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2519 
2520   /* Setting dofs splitting in mat_graph->which_dof */
2521   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
2522     PetscInt *is_indices;
2523     PetscInt is_size;
2524     for(i=0;i<pcbddc->n_ISForDofs;i++) {
2525       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
2526       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
2527       for(j=0;j<is_size;j++) {
2528         mat_graph->which_dof[is_indices[j]]=i;
2529       }
2530       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
2531     }
2532     /* use mat block size as vertex size */
2533     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
2534   } else { /* otherwise it assumes a constant block size */
2535     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
2536     for(i=0;i<mat_graph->nvtxs/bs;i++) {
2537       for(s=0;s<bs;s++) {
2538         mat_graph->which_dof[i*bs+s]=s;
2539       }
2540     }
2541     vertex_size=1;
2542   }
2543   /* count number of neigh per node */
2544   total_counts=0;
2545   for(i=1;i<pcis->n_neigh;i++){
2546     s=pcis->n_shared[i];
2547     total_counts+=s;
2548     for(j=0;j<s;j++){
2549       mat_graph->count[pcis->shared[i][j]] += 1;
2550     }
2551   }
2552   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
2553   if(pcbddc->NeumannBoundaries) {
2554     ierr = ISGetSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
2555     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
2556     for(i=0;i<neumann_bsize;i++){
2557       iindex = neumann_nodes[i];
2558       if(mat_graph->count[iindex] > 1){
2559         mat_graph->count[iindex]+=1;
2560         total_counts++;
2561       }
2562     }
2563   }
2564   /* allocate space for storing the set of neighbours of each node */
2565   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
2566   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr); }
2567   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2568   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2569   for(i=1;i<pcis->n_neigh;i++){
2570     s=pcis->n_shared[i];
2571     for(j=0;j<s;j++) {
2572       k=pcis->shared[i][j];
2573       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
2574       mat_graph->count[k]+=1;
2575     }
2576   }
2577   /* set -1 fake neighbour to mimic Neumann boundary */
2578   if(pcbddc->NeumannBoundaries) {
2579     for(i=0;i<neumann_bsize;i++){
2580       iindex = neumann_nodes[i];
2581       if(mat_graph->count[iindex] > 1){
2582         neighbours_set[iindex][mat_graph->count[iindex]] = -1;
2583         mat_graph->count[iindex]+=1;
2584       }
2585     }
2586     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
2587   }
2588   /* sort set of sharing subdomains (needed for comparison below) */
2589   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
2590   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
2591   if(pcbddc->DirichletBoundaries) {
2592     ierr = ISGetSize(pcbddc->DirichletBoundaries,&dirichlet_bsize);CHKERRQ(ierr);
2593     ierr = ISGetIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
2594     for(i=0;i<dirichlet_bsize;i++){
2595       mat_graph->count[dirichlet_nodes[i]]=0;
2596     }
2597     ierr = ISRestoreIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
2598   }
2599   for(i=0;i<mat_graph->nvtxs;i++){
2600     if(!mat_graph->count[i]){  /* interior nodes */
2601       mat_graph->touched[i]=PETSC_TRUE;
2602       mat_graph->where[i]=0;
2603       nodes_touched++;
2604     }
2605   }
2606   mat_graph->ncmps = 0;
2607   while(nodes_touched<mat_graph->nvtxs) {
2608     /*  find first untouched node in local ordering */
2609     i=0;
2610     while(mat_graph->touched[i]) i++;
2611     mat_graph->touched[i]=PETSC_TRUE;
2612     mat_graph->where[i]=where_values;
2613     nodes_touched++;
2614     /* now find all other nodes having the same set of sharing subdomains */
2615     for(j=i+1;j<mat_graph->nvtxs;j++){
2616       /* check for same number of sharing subdomains and dof number */
2617       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2618         /* check for same set of sharing subdomains */
2619         same_set=PETSC_TRUE;
2620         for(k=0;k<mat_graph->count[j];k++){
2621           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
2622             same_set=PETSC_FALSE;
2623           }
2624         }
2625         /* I found a friend of mine */
2626         if(same_set) {
2627           mat_graph->where[j]=where_values;
2628           mat_graph->touched[j]=PETSC_TRUE;
2629           nodes_touched++;
2630         }
2631       }
2632     }
2633     where_values++;
2634   }
2635   where_values--; if(where_values<0) where_values=0;
2636   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2637   /* Find connected components defined on the shared interface */
2638   if(where_values) {
2639     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2640     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2641     for(i=0;i<mat_graph->ncmps;i++) {
2642       ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2643       ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2644     }
2645   }
2646   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2647   for(i=0;i<where_values;i++) {
2648     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
2649     if(mat_graph->where_ncmps[i]>1) {
2650       adapt_interface=1;
2651       break;
2652     }
2653   }
2654   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2655   if(where_values && adapt_interface_reduced) {
2656 
2657     printf("Adapting Interface\n");
2658 
2659     PetscInt sum_requests=0,my_rank;
2660     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2661     PetscInt temp_buffer_size,ins_val,global_where_counter;
2662     PetscInt *cum_recv_counts;
2663     PetscInt *where_to_nodes_indices;
2664     PetscInt *petsc_buffer;
2665     PetscMPIInt *recv_buffer;
2666     PetscMPIInt *recv_buffer_where;
2667     PetscMPIInt *send_buffer;
2668     PetscMPIInt size_of_send;
2669     PetscInt *sizes_of_sends;
2670     MPI_Request *send_requests;
2671     MPI_Request *recv_requests;
2672     PetscInt *where_cc_adapt;
2673     PetscInt **temp_buffer;
2674     PetscInt *nodes_to_temp_buffer_indices;
2675     PetscInt *add_to_where;
2676 
2677     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2678     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2679     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2680     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2681     /* first count how many neighbours per connected component I will receive from */
2682     cum_recv_counts[0]=0;
2683     for(i=1;i<where_values+1;i++){
2684       j=0;
2685       while(mat_graph->where[j] != i) j++;
2686       where_to_nodes_indices[i-1]=j;
2687       if(neighbours_set[j][0]!=-1) { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]; } /* We don't want sends/recvs_to/from_self -> here I don't count myself  */
2688       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2689     }
2690     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2691     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2692     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2693     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2694     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2695     for(i=0;i<cum_recv_counts[where_values];i++) {
2696       send_requests[i]=MPI_REQUEST_NULL;
2697       recv_requests[i]=MPI_REQUEST_NULL;
2698     }
2699     /* exchange with my neighbours the number of my connected components on the shared interface */
2700     for(i=0;i<where_values;i++){
2701       j=where_to_nodes_indices[i];
2702       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2703       for(;k<mat_graph->count[j];k++){
2704         ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2705         ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2706         sum_requests++;
2707       }
2708     }
2709     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2710     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2711     /* determine the connected component I need to adapt */
2712     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2713     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2714     for(i=0;i<where_values;i++){
2715       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
2716         /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
2717         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2718           where_cc_adapt[i]=PETSC_TRUE;
2719           break;
2720         }
2721       }
2722     }
2723     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2724     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2725     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2726     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2727     sum_requests=0;
2728     start_of_send=0;
2729     start_of_recv=cum_recv_counts[where_values];
2730     for(i=0;i<where_values;i++) {
2731       if(where_cc_adapt[i]) {
2732         size_of_send=0;
2733         for(j=i;j<mat_graph->ncmps;j++) {
2734           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2735             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2736             size_of_send+=1;
2737             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2738               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2739             }
2740             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2741           }
2742         }
2743         j = where_to_nodes_indices[i];
2744         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2745         for(;k<mat_graph->count[j];k++){
2746           ierr = MPI_Isend(&size_of_send,1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2747           ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2748           sum_requests++;
2749         }
2750         sizes_of_sends[i]=size_of_send;
2751         start_of_send+=size_of_send;
2752       }
2753     }
2754     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2755     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2756     buffer_size=0;
2757     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2758     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2759     /* now exchange the data */
2760     start_of_recv=0;
2761     start_of_send=0;
2762     sum_requests=0;
2763     for(i=0;i<where_values;i++) {
2764       if(where_cc_adapt[i]) {
2765         size_of_send = sizes_of_sends[i];
2766         j = where_to_nodes_indices[i];
2767         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2768         for(;k<mat_graph->count[j];k++){
2769           ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2770           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2771           ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2772           start_of_recv+=size_of_recv;
2773           sum_requests++;
2774         }
2775         start_of_send+=size_of_send;
2776       }
2777     }
2778     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2779     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2780     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2781     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2782     for(j=0;j<buffer_size;) {
2783        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2784        k=petsc_buffer[j]+1;
2785        j+=k;
2786     }
2787     sum_requests=cum_recv_counts[where_values];
2788     start_of_recv=0;
2789     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2790     global_where_counter=0;
2791     for(i=0;i<where_values;i++){
2792       if(where_cc_adapt[i]){
2793         temp_buffer_size=0;
2794         /* find nodes on the shared interface we need to adapt */
2795         for(j=0;j<mat_graph->nvtxs;j++){
2796           if(mat_graph->where[j]==i+1) {
2797             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2798             temp_buffer_size++;
2799           } else {
2800             nodes_to_temp_buffer_indices[j]=-1;
2801           }
2802         }
2803         /* allocate some temporary space */
2804         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2805         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2806         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2807         for(j=1;j<temp_buffer_size;j++){
2808           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2809         }
2810         /* analyze contributions from neighbouring subdomains for i-th conn comp
2811            temp buffer structure:
2812            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2813            3 neighs procs with structured connected components:
2814              neigh 0: [0 1 4], [2 3];  (2 connected components)
2815              neigh 1: [0 1], [2 3 4];  (2 connected components)
2816              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2817            tempbuffer (row-oriented) should be filled as:
2818              [ 0, 0, 0;
2819                0, 0, 1;
2820                1, 1, 2;
2821                1, 1, 2;
2822                0, 1, 0; ];
2823            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2824            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2825                                                                                                                                    */
2826         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2827           ins_val=0;
2828           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2829           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2830             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2831               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2832             }
2833             buffer_size+=k;
2834             ins_val++;
2835           }
2836           start_of_recv+=size_of_recv;
2837           sum_requests++;
2838         }
2839         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2840         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2841         for(j=0;j<temp_buffer_size;j++){
2842           if(!add_to_where[j]){ /* found a new cc  */
2843             global_where_counter++;
2844             add_to_where[j]=global_where_counter;
2845             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2846               same_set=PETSC_TRUE;
2847               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2848                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2849                   same_set=PETSC_FALSE;
2850                   break;
2851                 }
2852               }
2853               if(same_set) add_to_where[k]=global_where_counter;
2854             }
2855           }
2856         }
2857         /* insert new data in where array */
2858         temp_buffer_size=0;
2859         for(j=0;j<mat_graph->nvtxs;j++){
2860           if(mat_graph->where[j]==i+1) {
2861             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2862             temp_buffer_size++;
2863           }
2864         }
2865         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2866         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2867         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2868       }
2869     }
2870     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2871     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2872     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2873     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2874     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2875     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2876     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2877     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2878     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2879     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2880     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2881     if(global_where_counter) {
2882       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2883       global_where_counter=0;
2884       for(i=0;i<mat_graph->nvtxs;i++){
2885         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2886           global_where_counter++;
2887           for(j=i+1;j<mat_graph->nvtxs;j++){
2888             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2889               mat_graph->where[j]=global_where_counter;
2890               mat_graph->touched[j]=PETSC_TRUE;
2891             }
2892           }
2893           mat_graph->where[i]=global_where_counter;
2894           mat_graph->touched[i]=PETSC_TRUE;
2895         }
2896       }
2897       where_values=global_where_counter;
2898     }
2899     if(global_where_counter) {
2900       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2901       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2902       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2903       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2904       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2905       for(i=0;i<mat_graph->ncmps;i++) {
2906         ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2907         ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2908       }
2909     }
2910   } /* Finished adapting interface */
2911   PetscInt nfc=0;
2912   PetscInt nec=0;
2913   PetscInt nvc=0;
2914   PetscBool twodim_flag=PETSC_FALSE;
2915   for (i=0; i<mat_graph->ncmps; i++) {
2916     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
2917       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
2918         nfc++;
2919       } else { /* note that nec will be zero in 2d */
2920         nec++;
2921       }
2922     } else {
2923       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
2924     }
2925   }
2926 
2927   if(!nec) { /* we are in a 2d case -> no faces, only edges */
2928     nec = nfc;
2929     nfc = 0;
2930     twodim_flag = PETSC_TRUE;
2931   }
2932   /* allocate IS arrays for faces, edges. Vertices need a single index set.
2933      Reusing space allocated in mat_graph->where for creating IS objects */
2934   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
2935     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
2936     use_faces=PETSC_TRUE;
2937   }
2938   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
2939     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
2940     use_edges=PETSC_TRUE;
2941   }
2942   nfc=0;
2943   nec=0;
2944   for (i=0; i<mat_graph->ncmps; i++) {
2945     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
2946       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
2947         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
2948       }
2949       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
2950         if(twodim_flag) {
2951           if(use_edges) {
2952             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
2953             nec++;
2954           }
2955         } else {
2956           if(use_faces) {
2957             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
2958             nfc++;
2959           }
2960         }
2961       } else {
2962         if(use_edges) {
2963           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
2964           nec++;
2965         }
2966       }
2967     }
2968   }
2969   pcbddc->n_ISForFaces=nfc;
2970   pcbddc->n_ISForEdges=nec;
2971   nvc=0;
2972   if( !pcbddc->constraints_flag ) {
2973     for (i=0; i<mat_graph->ncmps; i++) {
2974       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
2975         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
2976           mat_graph->where[nvc]=mat_graph->queue[j];
2977           nvc++;
2978         }
2979       }
2980     }
2981   }
2982   /* sort vertex set (by local ordering) */
2983   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
2984   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
2985 
2986   if(pcbddc->dbg_flag) {
2987     PetscViewer viewer=pcbddc->dbg_viewer;
2988 
2989     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2990     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2991     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2992 /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
2993     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2994     for(i=0;i<mat_graph->nvtxs;i++) {
2995       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);CHKERRQ(ierr);
2996       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
2997         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
2998       }
2999       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
3000     }
3001     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
3002     for(i=0;i<mat_graph->ncmps;i++) {
3003       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
3004              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
3005       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
3006         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
3007       }
3008     }
3009     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);*/
3010     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
3011     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
3012     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3013     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3014   }
3015 
3016   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
3017   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
3018   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
3019   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
3020   /* Free graph structure */
3021   if(mat_graph->nvtxs){
3022     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
3023     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
3024     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3025     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3026     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
3027   }
3028   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
3029 
3030   PetscFunctionReturn(0);
3031 
3032 }
3033 
3034 /* -------------------------------------------------------------------------- */
3035 
3036 /* The following code has been adapted from function IsConnectedSubdomain contained
3037    in source file contig.c of METIS library (version 5.0.1)                           */
3038 
3039 #undef __FUNCT__
3040 #define __FUNCT__ "PCBDDCFindConnectedComponents"
3041 static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
3042 {
3043   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
3044   PetscInt *xadj, *adjncy, *where, *queue;
3045   PetscInt *cptr;
3046   PetscBool *touched;
3047 
3048   PetscFunctionBegin;
3049 
3050   nvtxs   = graph->nvtxs;
3051   xadj    = graph->xadj;
3052   adjncy  = graph->adjncy;
3053   where   = graph->where;
3054   touched = graph->touched;
3055   queue   = graph->queue;
3056   cptr    = graph->cptr;
3057 
3058   for (i=0; i<nvtxs; i++)
3059     touched[i] = PETSC_FALSE;
3060 
3061   cum_queue=0;
3062   ncmps=0;
3063 
3064   for(n=0; n<n_dist; n++) {
3065     pid = n+1;
3066     nleft = 0;
3067     for (i=0; i<nvtxs; i++) {
3068       if (where[i] == pid)
3069         nleft++;
3070     }
3071     for (i=0; i<nvtxs; i++) {
3072       if (where[i] == pid)
3073         break;
3074     }
3075     touched[i] = PETSC_TRUE;
3076     queue[cum_queue] = i;
3077     first = 0; last = 1;
3078     cptr[ncmps] = cum_queue;  /* This actually points to queue */
3079     ncmps_pid = 0;
3080     while (first != nleft) {
3081       if (first == last) { /* Find another starting vertex */
3082         cptr[++ncmps] = first+cum_queue;
3083         ncmps_pid++;
3084         for (i=0; i<nvtxs; i++) {
3085           if (where[i] == pid && !touched[i])
3086             break;
3087         }
3088         queue[cum_queue+last] = i;
3089         last++;
3090         touched[i] = PETSC_TRUE;
3091       }
3092       i = queue[cum_queue+first];
3093       first++;
3094       for (j=xadj[i]; j<xadj[i+1]; j++) {
3095         k = adjncy[j];
3096         if (where[k] == pid && !touched[k]) {
3097           queue[cum_queue+last] = k;
3098           last++;
3099           touched[k] = PETSC_TRUE;
3100         }
3101       }
3102     }
3103     cptr[++ncmps] = first+cum_queue;
3104     ncmps_pid++;
3105     cum_queue=cptr[ncmps];
3106     graph->where_ncmps[n] = ncmps_pid;
3107   }
3108   graph->ncmps = ncmps;
3109 
3110   PetscFunctionReturn(0);
3111 }
3112 
3113