xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision da1bb401672dd0ab571ef3eb7da9ad4ecf0f40f6)
153cdbc3dSStefano Zampini /* TODOLIST
2*da1bb401SStefano Zampini    DofSplitting and DM attached to pc?
3*da1bb401SStefano Zampini    Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
4*da1bb401SStefano Zampini    Exact solvers: Solve local saddle point directly
5831a100dSStefano Zampini      - change prec_type to switch_inexact_prec_type
6831a100dSStefano Zampini      - add bool solve_exact_saddle_point slot to pdbddc data
73b03a366Sstefano_zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
8a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
9a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
10a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
11a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
12a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
133b03a366Sstefano_zampini      - Add levels' slot to bddc data structure and associated Set/Get functions
14a0ba757dSStefano Zampini    code refactoring:
15a0ba757dSStefano Zampini      - pick up better names for static functions
16a0ba757dSStefano Zampini    change options structure:
17a0ba757dSStefano Zampini      - insert BDDC into MG framework?
18a0ba757dSStefano Zampini    provide other ops? Ask to developers
19a0ba757dSStefano Zampini    remove all unused printf
20a0ba757dSStefano Zampini    man pages
2153cdbc3dSStefano Zampini */
220c7d97c5SJed Brown 
2353cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
240c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
250c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2653cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2753cdbc3dSStefano Zampini 
2853cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
293b03a366Sstefano_zampini #include <petscblaslapack.h>
300c7d97c5SJed Brown 
310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
320c7d97c5SJed Brown #undef __FUNCT__
330c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
340c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
350c7d97c5SJed Brown {
360c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
370c7d97c5SJed Brown   PetscErrorCode ierr;
380c7d97c5SJed Brown 
390c7d97c5SJed Brown   PetscFunctionBegin;
400c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Verbose debugging of main data structures */
42e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
430c7d97c5SJed Brown   /* Some customization for default primal space */
44*da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use only vertices in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
45*da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use only constraints in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
46*da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use only faces among constraints of coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
47*da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use only edges among constraints of coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
480c7d97c5SJed Brown   /* Coarse solver context */
49*da1bb401SStefano Zampini   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; /*order of choiches depends on ENUM defined in bddc.h */
500c7d97c5SJed Brown   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);
510c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
520c7d97c5SJed Brown   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);
530c7d97c5SJed Brown   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr);
540c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
550c7d97c5SJed Brown   PetscFunctionReturn(0);
560c7d97c5SJed Brown }
570c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
580c7d97c5SJed Brown EXTERN_C_BEGIN
590c7d97c5SJed Brown #undef __FUNCT__
600c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
620c7d97c5SJed Brown {
630c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
640c7d97c5SJed Brown 
650c7d97c5SJed Brown   PetscFunctionBegin;
660c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
670c7d97c5SJed Brown   PetscFunctionReturn(0);
680c7d97c5SJed Brown }
690c7d97c5SJed Brown EXTERN_C_END
700c7d97c5SJed Brown #undef __FUNCT__
710c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7253cdbc3dSStefano Zampini /*@
739c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7453cdbc3dSStefano Zampini 
759c0446d6SStefano Zampini    Not collective
7653cdbc3dSStefano Zampini 
7753cdbc3dSStefano Zampini    Input Parameters:
7853cdbc3dSStefano Zampini +  pc - the preconditioning context
7953cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8053cdbc3dSStefano Zampini 
8153cdbc3dSStefano Zampini    Level: intermediate
8253cdbc3dSStefano Zampini 
8353cdbc3dSStefano Zampini    Notes:
84*da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
8553cdbc3dSStefano Zampini 
8653cdbc3dSStefano Zampini .seealso: PCBDDC
8753cdbc3dSStefano Zampini @*/
880c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
890c7d97c5SJed Brown {
900c7d97c5SJed Brown   PetscErrorCode ierr;
910c7d97c5SJed Brown 
920c7d97c5SJed Brown   PetscFunctionBegin;
930c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
940c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
950c7d97c5SJed Brown   PetscFunctionReturn(0);
960c7d97c5SJed Brown }
970c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
980c7d97c5SJed Brown EXTERN_C_BEGIN
990c7d97c5SJed Brown #undef __FUNCT__
1003b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
1013b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
1023b03a366Sstefano_zampini {
1033b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1043b03a366Sstefano_zampini   PetscErrorCode ierr;
1053b03a366Sstefano_zampini 
1063b03a366Sstefano_zampini   PetscFunctionBegin;
1073b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
10836e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
10936e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
1103b03a366Sstefano_zampini   PetscFunctionReturn(0);
1113b03a366Sstefano_zampini }
1123b03a366Sstefano_zampini EXTERN_C_END
1133b03a366Sstefano_zampini #undef __FUNCT__
1143b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
1153b03a366Sstefano_zampini /*@
116*da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
117*da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
1183b03a366Sstefano_zampini 
1193b03a366Sstefano_zampini    Not collective
1203b03a366Sstefano_zampini 
1213b03a366Sstefano_zampini    Input Parameters:
1223b03a366Sstefano_zampini +  pc - the preconditioning context
1233b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
1243b03a366Sstefano_zampini 
1253b03a366Sstefano_zampini    Level: intermediate
1263b03a366Sstefano_zampini 
1273b03a366Sstefano_zampini    Notes:
1283b03a366Sstefano_zampini 
1293b03a366Sstefano_zampini .seealso: PCBDDC
1303b03a366Sstefano_zampini @*/
1313b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
1323b03a366Sstefano_zampini {
1333b03a366Sstefano_zampini   PetscErrorCode ierr;
1343b03a366Sstefano_zampini 
1353b03a366Sstefano_zampini   PetscFunctionBegin;
1363b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1373b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
1383b03a366Sstefano_zampini   PetscFunctionReturn(0);
1393b03a366Sstefano_zampini }
1403b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1413b03a366Sstefano_zampini EXTERN_C_BEGIN
1423b03a366Sstefano_zampini #undef __FUNCT__
1430c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
14453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1450c7d97c5SJed Brown {
1460c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
14753cdbc3dSStefano Zampini   PetscErrorCode ierr;
1480c7d97c5SJed Brown 
1490c7d97c5SJed Brown   PetscFunctionBegin;
15053cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
15136e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
15236e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
1530c7d97c5SJed Brown   PetscFunctionReturn(0);
1540c7d97c5SJed Brown }
1550c7d97c5SJed Brown EXTERN_C_END
1560c7d97c5SJed Brown #undef __FUNCT__
1570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
15857527edcSJed Brown /*@
159*da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
160*da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
16157527edcSJed Brown 
1629c0446d6SStefano Zampini    Not collective
16357527edcSJed Brown 
16457527edcSJed Brown    Input Parameters:
16557527edcSJed Brown +  pc - the preconditioning context
1669c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
16757527edcSJed Brown 
16857527edcSJed Brown    Level: intermediate
16957527edcSJed Brown 
17057527edcSJed Brown    Notes:
17157527edcSJed Brown 
17257527edcSJed Brown .seealso: PCBDDC
17357527edcSJed Brown @*/
17453cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1750c7d97c5SJed Brown {
1760c7d97c5SJed Brown   PetscErrorCode ierr;
1770c7d97c5SJed Brown 
1780c7d97c5SJed Brown   PetscFunctionBegin;
1790c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18053cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
18153cdbc3dSStefano Zampini   PetscFunctionReturn(0);
18253cdbc3dSStefano Zampini }
18353cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
18453cdbc3dSStefano Zampini EXTERN_C_BEGIN
18553cdbc3dSStefano Zampini #undef __FUNCT__
186*da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
187*da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
188*da1bb401SStefano Zampini {
189*da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
190*da1bb401SStefano Zampini 
191*da1bb401SStefano Zampini   PetscFunctionBegin;
192*da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
193*da1bb401SStefano Zampini   PetscFunctionReturn(0);
194*da1bb401SStefano Zampini }
195*da1bb401SStefano Zampini EXTERN_C_END
196*da1bb401SStefano Zampini #undef __FUNCT__
197*da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
198*da1bb401SStefano Zampini /*@
199*da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
200*da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
201*da1bb401SStefano Zampini 
202*da1bb401SStefano Zampini    Not collective
203*da1bb401SStefano Zampini 
204*da1bb401SStefano Zampini    Input Parameters:
205*da1bb401SStefano Zampini +  pc - the preconditioning context
206*da1bb401SStefano Zampini 
207*da1bb401SStefano Zampini    Output Parameters:
208*da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
209*da1bb401SStefano Zampini 
210*da1bb401SStefano Zampini    Level: intermediate
211*da1bb401SStefano Zampini 
212*da1bb401SStefano Zampini    Notes:
213*da1bb401SStefano Zampini 
214*da1bb401SStefano Zampini .seealso: PCBDDC
215*da1bb401SStefano Zampini @*/
216*da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
217*da1bb401SStefano Zampini {
218*da1bb401SStefano Zampini   PetscErrorCode ierr;
219*da1bb401SStefano Zampini 
220*da1bb401SStefano Zampini   PetscFunctionBegin;
221*da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
222*da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
223*da1bb401SStefano Zampini   PetscFunctionReturn(0);
224*da1bb401SStefano Zampini }
225*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
226*da1bb401SStefano Zampini EXTERN_C_BEGIN
227*da1bb401SStefano Zampini #undef __FUNCT__
22853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
22953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
23053cdbc3dSStefano Zampini {
23153cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
23253cdbc3dSStefano Zampini 
23353cdbc3dSStefano Zampini   PetscFunctionBegin;
23453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
23553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
23653cdbc3dSStefano Zampini }
23753cdbc3dSStefano Zampini EXTERN_C_END
23853cdbc3dSStefano Zampini #undef __FUNCT__
23953cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
24053cdbc3dSStefano Zampini /*@
241*da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
242*da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
24353cdbc3dSStefano Zampini 
2449c0446d6SStefano Zampini    Not collective
24553cdbc3dSStefano Zampini 
24653cdbc3dSStefano Zampini    Input Parameters:
24753cdbc3dSStefano Zampini +  pc - the preconditioning context
24853cdbc3dSStefano Zampini 
24953cdbc3dSStefano Zampini    Output Parameters:
25053cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
25153cdbc3dSStefano Zampini 
25253cdbc3dSStefano Zampini    Level: intermediate
25353cdbc3dSStefano Zampini 
25453cdbc3dSStefano Zampini    Notes:
25553cdbc3dSStefano Zampini 
25653cdbc3dSStefano Zampini .seealso: PCBDDC
25753cdbc3dSStefano Zampini @*/
25853cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
25953cdbc3dSStefano Zampini {
26053cdbc3dSStefano Zampini   PetscErrorCode ierr;
26153cdbc3dSStefano Zampini 
26253cdbc3dSStefano Zampini   PetscFunctionBegin;
26353cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
26453cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
2650c7d97c5SJed Brown   PetscFunctionReturn(0);
2660c7d97c5SJed Brown }
26736e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
26836e030ebSStefano Zampini EXTERN_C_BEGIN
26936e030ebSStefano Zampini #undef __FUNCT__
270*da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
271*da1bb401SStefano Zampini static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, PetscInt xadj[], PetscInt adjncy[], PetscCopyMode copymode)
27236e030ebSStefano Zampini {
27336e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
274*da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
275*da1bb401SStefano Zampini   PetscErrorCode ierr;
27636e030ebSStefano Zampini 
27736e030ebSStefano Zampini   PetscFunctionBegin;
278*da1bb401SStefano Zampini   mat_graph->nvtxs=nvtxs;
279*da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->xadj);CHKERRQ(ierr);
280*da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->adjncy);CHKERRQ(ierr);
281*da1bb401SStefano Zampini   if(copymode == PETSC_COPY_VALUES) {
282*da1bb401SStefano Zampini     ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
283*da1bb401SStefano Zampini     ierr = PetscMalloc(xadj[mat_graph->nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
284*da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
285*da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[mat_graph->nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
286*da1bb401SStefano Zampini   } else if(copymode == PETSC_OWN_POINTER) {
287*da1bb401SStefano Zampini     mat_graph->xadj=xadj;
288*da1bb401SStefano Zampini     mat_graph->adjncy=adjncy;
289*da1bb401SStefano Zampini   } else {
290*da1bb401SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
291*da1bb401SStefano Zampini   }
29236e030ebSStefano Zampini   PetscFunctionReturn(0);
29336e030ebSStefano Zampini }
29436e030ebSStefano Zampini EXTERN_C_END
29536e030ebSStefano Zampini #undef __FUNCT__
296*da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
29736e030ebSStefano Zampini /*@
298*da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
29936e030ebSStefano Zampini 
30036e030ebSStefano Zampini    Not collective
30136e030ebSStefano Zampini 
30236e030ebSStefano Zampini    Input Parameters:
30336e030ebSStefano Zampini +  pc - the preconditioning context
304*da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
305*da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
306*da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
307*da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
30836e030ebSStefano Zampini 
30936e030ebSStefano Zampini    Level: intermediate
31036e030ebSStefano Zampini 
31136e030ebSStefano Zampini    Notes:
31236e030ebSStefano Zampini 
31336e030ebSStefano Zampini .seealso: PCBDDC
31436e030ebSStefano Zampini @*/
315*da1bb401SStefano Zampini PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,PetscInt xadj[],PetscInt adjncy[], PetscCopyMode copymode)
31636e030ebSStefano Zampini {
317*da1bb401SStefano Zampini   PetscInt       nrows,ncols;
318*da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
31936e030ebSStefano Zampini   PetscErrorCode ierr;
32036e030ebSStefano Zampini 
32136e030ebSStefano Zampini   PetscFunctionBegin;
32236e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
323*da1bb401SStefano Zampini   ierr = MatGetSize(matis->A,&nrows,&ncols);CHKERRQ(ierr);
324*da1bb401SStefano Zampini   if(nvtxs != nrows) {
325*da1bb401SStefano Zampini     SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local adjacency size %d passed in %s differs from local problem size %d!\n",nvtxs,__FUNCT__,nrows);
326*da1bb401SStefano Zampini   } else {
327*da1bb401SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,PetscInt[],PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
328*da1bb401SStefano Zampini   }
32936e030ebSStefano Zampini   PetscFunctionReturn(0);
33036e030ebSStefano Zampini }
3319c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
3329c0446d6SStefano Zampini EXTERN_C_BEGIN
3339c0446d6SStefano Zampini #undef __FUNCT__
3349c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
3359c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
3369c0446d6SStefano Zampini {
3379c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3389c0446d6SStefano Zampini   PetscInt i;
3399c0446d6SStefano Zampini   PetscErrorCode ierr;
3409c0446d6SStefano Zampini 
3419c0446d6SStefano Zampini   PetscFunctionBegin;
342*da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
3439c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
3449c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3459c0446d6SStefano Zampini   }
346d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
347*da1bb401SStefano Zampini   /* allocate space then set */
3489c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
3499c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
350*da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
351*da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
3529c0446d6SStefano Zampini   }
3539c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
3549c0446d6SStefano Zampini   PetscFunctionReturn(0);
3559c0446d6SStefano Zampini }
3569c0446d6SStefano Zampini EXTERN_C_END
3579c0446d6SStefano Zampini #undef __FUNCT__
3589c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
3599c0446d6SStefano Zampini /*@
360*da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
3619c0446d6SStefano Zampini 
3629c0446d6SStefano Zampini    Not collective
3639c0446d6SStefano Zampini 
3649c0446d6SStefano Zampini    Input Parameters:
3659c0446d6SStefano Zampini +  pc - the preconditioning context
366*da1bb401SStefano Zampini -  n - number of index sets defining the fields
367*da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
3689c0446d6SStefano Zampini 
3699c0446d6SStefano Zampini    Level: intermediate
3709c0446d6SStefano Zampini 
3719c0446d6SStefano Zampini    Notes:
3729c0446d6SStefano Zampini 
3739c0446d6SStefano Zampini .seealso: PCBDDC
3749c0446d6SStefano Zampini @*/
3759c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
3769c0446d6SStefano Zampini {
3779c0446d6SStefano Zampini   PetscErrorCode ierr;
3789c0446d6SStefano Zampini 
3799c0446d6SStefano Zampini   PetscFunctionBegin;
3809c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3819c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
3829c0446d6SStefano Zampini   PetscFunctionReturn(0);
3839c0446d6SStefano Zampini }
384*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
3859c0446d6SStefano Zampini 
38653cdbc3dSStefano Zampini #undef __FUNCT__
38753cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
3880c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3890c7d97c5SJed Brown /*
3900c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
3910c7d97c5SJed Brown                   by setting data structures and options.
3920c7d97c5SJed Brown 
3930c7d97c5SJed Brown    Input Parameter:
39453cdbc3dSStefano Zampini +  pc - the preconditioner context
3950c7d97c5SJed Brown 
3960c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
3970c7d97c5SJed Brown 
3980c7d97c5SJed Brown    Notes:
3990c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
4000c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
4010c7d97c5SJed Brown */
40253cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
4030c7d97c5SJed Brown {
4040c7d97c5SJed Brown   PetscErrorCode ierr;
4050c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
4060c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
4070c7d97c5SJed Brown 
4080c7d97c5SJed Brown   PetscFunctionBegin;
4090c7d97c5SJed Brown   if (!pc->setupcalled) {
4103b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
4119c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
4120c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
4130c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
4140c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
4150c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
4160c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
4173b03a366Sstefano_zampini     /* Get stdout for dbg */
418e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
419e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
420e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
421e269702eSStefano Zampini     }
4223b03a366Sstefano_zampini     /* TODO MOVE CODE FRAGMENT */
4230c7d97c5SJed Brown     PetscInt im_active=0;
4240c7d97c5SJed Brown     if(pcis->n) im_active = 1;
42553cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
4263b03a366Sstefano_zampini     /* Analyze local interface */
4270c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
4283b03a366Sstefano_zampini     /* Set up local constraint matrix */
4293b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
4300c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
4310c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
4323b03a366Sstefano_zampini     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
4333b03a366Sstefano_zampini     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
4340c7d97c5SJed Brown   }
4350c7d97c5SJed Brown   PetscFunctionReturn(0);
4360c7d97c5SJed Brown }
4370c7d97c5SJed Brown 
4380c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4390c7d97c5SJed Brown /*
4400c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
4410c7d97c5SJed Brown 
4420c7d97c5SJed Brown    Input Parameters:
4430c7d97c5SJed Brown .  pc - the preconditioner context
4440c7d97c5SJed Brown .  r - input vector (global)
4450c7d97c5SJed Brown 
4460c7d97c5SJed Brown    Output Parameter:
4470c7d97c5SJed Brown .  z - output vector (global)
4480c7d97c5SJed Brown 
4490c7d97c5SJed Brown    Application Interface Routine: PCApply()
4500c7d97c5SJed Brown  */
4510c7d97c5SJed Brown #undef __FUNCT__
4520c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
45353cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
4540c7d97c5SJed Brown {
4550c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
4560c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
4570c7d97c5SJed Brown   PetscErrorCode    ierr;
4583b03a366Sstefano_zampini   const PetscScalar one = 1.0;
4593b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
4600c7d97c5SJed Brown 
4610c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
4620c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
4630c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
4640c7d97c5SJed Brown 
4650c7d97c5SJed Brown   PetscFunctionBegin;
4660c7d97c5SJed Brown   /* First Dirichlet solve */
4670c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4680c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
4700c7d97c5SJed Brown   /*
4710c7d97c5SJed Brown     Assembling right hand side for BDDC operator
4720c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
4730c7d97c5SJed Brown     - the interface part of the global vector z
4740c7d97c5SJed Brown   */
4750c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4760c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
4770c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4780c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4790c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
4800c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4810c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4820c7d97c5SJed Brown 
4830c7d97c5SJed Brown   /*
4840c7d97c5SJed Brown     Apply interface preconditioner
4850c7d97c5SJed Brown     Results are stored in:
4860c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
4870c7d97c5SJed Brown     -  the interface part of the global vector z
4880c7d97c5SJed Brown   */
4890c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
4900c7d97c5SJed Brown 
4913b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
4920c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4930c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4940c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
4950c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
49653cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
4970c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
4980c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
4990c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
5000c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5010c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5020c7d97c5SJed Brown 
5030c7d97c5SJed Brown   PetscFunctionReturn(0);
5040c7d97c5SJed Brown 
5050c7d97c5SJed Brown }
506*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
507*da1bb401SStefano Zampini #undef __FUNCT__
508*da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
509*da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
510*da1bb401SStefano Zampini {
511*da1bb401SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
512*da1bb401SStefano Zampini   PetscErrorCode ierr;
513*da1bb401SStefano Zampini 
514*da1bb401SStefano Zampini   PetscFunctionBegin;
515*da1bb401SStefano Zampini   /* free data created by PCIS */
516*da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
517*da1bb401SStefano Zampini   /* free BDDC data  */
518*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
519*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
520*da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
521*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
522*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
523*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
524*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
525*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
526*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
527*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
528*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
529*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
530*da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
531*da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
532*da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
533*da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
534*da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
535*da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
536*da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
537*da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
538*da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
539*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
540*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
541*da1bb401SStefano Zampini   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
542*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
543*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
544*da1bb401SStefano Zampini   PetscInt i;
545*da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
546*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
547*da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
548*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
549*da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
550*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
551*da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
552*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->xadj);CHKERRQ(ierr);
553*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->adjncy);CHKERRQ(ierr);
554*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->neighbours_set[0]);CHKERRQ(ierr);
555*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->neighbours_set);CHKERRQ(ierr);
556*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
557*da1bb401SStefano Zampini   /* Free the private data structure that was hanging off the PC */
558*da1bb401SStefano Zampini   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
559*da1bb401SStefano Zampini   PetscFunctionReturn(0);
560*da1bb401SStefano Zampini }
5610c7d97c5SJed Brown 
5620c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
563*da1bb401SStefano Zampini /*MC
564*da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
5650c7d97c5SJed Brown 
566*da1bb401SStefano Zampini    Options Database Keys:
567*da1bb401SStefano Zampini .    -pcbddc ??? -
568*da1bb401SStefano Zampini 
569*da1bb401SStefano Zampini    Level: intermediate
570*da1bb401SStefano Zampini 
571*da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
572*da1bb401SStefano Zampini 
573*da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
574*da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
575*da1bb401SStefano Zampini           on the subdomains).
576*da1bb401SStefano Zampini 
577*da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
578*da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
579*da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
580*da1bb401SStefano Zampini 
581*da1bb401SStefano Zampini    Contributed by Stefano Zampini
582*da1bb401SStefano Zampini 
583*da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
584*da1bb401SStefano Zampini M*/
585*da1bb401SStefano Zampini EXTERN_C_BEGIN
586*da1bb401SStefano Zampini #undef __FUNCT__
587*da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
588*da1bb401SStefano Zampini PetscErrorCode PCCreate_BDDC(PC pc)
589*da1bb401SStefano Zampini {
590*da1bb401SStefano Zampini   PetscErrorCode ierr;
591*da1bb401SStefano Zampini   PC_BDDC        *pcbddc;
592*da1bb401SStefano Zampini   PCBDDCGraph    mat_graph;
593*da1bb401SStefano Zampini 
594*da1bb401SStefano Zampini   PetscFunctionBegin;
595*da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
596*da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
597*da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
598*da1bb401SStefano Zampini 
599*da1bb401SStefano Zampini   /* create PCIS data structure */
600*da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
601*da1bb401SStefano Zampini 
602*da1bb401SStefano Zampini   /* BDDC specific */
603*da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
604*da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
605*da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
606*da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
607*da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
608*da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
609*da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
610*da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
611*da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
612*da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
613*da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
614*da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
615*da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
616*da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
617*da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
618*da1bb401SStefano Zampini   pcbddc->prec_type                  = PETSC_FALSE;
619*da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
620*da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
621*da1bb401SStefano Zampini   pcbddc->ISForVertices              = 0;
622*da1bb401SStefano Zampini   pcbddc->n_ISForFaces               = 0;
623*da1bb401SStefano Zampini   pcbddc->n_ISForEdges               = 0;
624*da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
625*da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
626*da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
627*da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
628*da1bb401SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
629*da1bb401SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
630*da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
631*da1bb401SStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
632*da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
633*da1bb401SStefano Zampini 
634*da1bb401SStefano Zampini   /* allocate and initialize needed graph structure */
635*da1bb401SStefano Zampini   ierr = PetscMalloc(sizeof(*mat_graph),&pcbddc->mat_graph);CHKERRQ(ierr);
636*da1bb401SStefano Zampini   pcbddc->mat_graph->xadj            = 0;
637*da1bb401SStefano Zampini   pcbddc->mat_graph->adjncy          = 0;
638*da1bb401SStefano Zampini 
639*da1bb401SStefano Zampini   /* function pointers */
640*da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
641*da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
642*da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
643*da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
644*da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
645*da1bb401SStefano Zampini   pc->ops->view                = 0;
646*da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
647*da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
648*da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
649*da1bb401SStefano Zampini 
650*da1bb401SStefano Zampini   /* composing function */
651*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
652*da1bb401SStefano Zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
653*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
654*da1bb401SStefano Zampini                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
655*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C","PCBDDCGetDirichletBoundaries_BDDC",
656*da1bb401SStefano Zampini                     PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
657*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
658*da1bb401SStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
659*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
660*da1bb401SStefano Zampini                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
661*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
662*da1bb401SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
663*da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C","PCBDDCSetLocalAdjacencyGraph_BDDC",
664*da1bb401SStefano Zampini                     PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
665*da1bb401SStefano Zampini   PetscFunctionReturn(0);
666*da1bb401SStefano Zampini }
667*da1bb401SStefano Zampini EXTERN_C_END
668*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
669*da1bb401SStefano Zampini /* All static functions from now on                                           */
670*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
671*da1bb401SStefano Zampini #undef __FUNCT__
672*da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetupLocalAdjacencyGraph"
673*da1bb401SStefano Zampini static PetscErrorCode PCBDDCSetupLocalAdjacencyGraph(PC pc)
674*da1bb401SStefano Zampini {
675*da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
676*da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
677*da1bb401SStefano Zampini   PetscInt       nvtxs,*xadj,*adjncy;
678*da1bb401SStefano Zampini   Mat            mat_adj;
679*da1bb401SStefano Zampini   PetscBool      symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE,flg_row=PETSC_TRUE;
680*da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
681*da1bb401SStefano Zampini   PetscErrorCode ierr;
682*da1bb401SStefano Zampini 
683*da1bb401SStefano Zampini   PetscFunctionBegin;
684*da1bb401SStefano Zampini   /* get CSR adjacency from local matrix if user has not yet provided local graph using PCBDDCSetLocalAdjacencyGraph function */
685*da1bb401SStefano Zampini   if(!mat_graph->xadj) {
686*da1bb401SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
687*da1bb401SStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
688*da1bb401SStefano Zampini     if(!flg_row) {
689*da1bb401SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
690*da1bb401SStefano Zampini     }
691*da1bb401SStefano Zampini     /* Get adjacency into BDDC workspace */
692*da1bb401SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
693*da1bb401SStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
694*da1bb401SStefano Zampini     if(!flg_row) {
695*da1bb401SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
696*da1bb401SStefano Zampini     }
697*da1bb401SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
698*da1bb401SStefano Zampini   }
699*da1bb401SStefano Zampini   PetscFunctionReturn(0);
700*da1bb401SStefano Zampini }
701*da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
7020c7d97c5SJed Brown #undef __FUNCT__
7030c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
70453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
7050c7d97c5SJed Brown {
7060c7d97c5SJed Brown   PetscErrorCode ierr;
7070c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
7080c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
7093b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
7100c7d97c5SJed Brown 
7110c7d97c5SJed Brown   PetscFunctionBegin;
7120c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
7130c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7140c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7150c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
7160c7d97c5SJed Brown 
7170c7d97c5SJed Brown   /* Application of PHI^T  */
7180c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
7190c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
7200c7d97c5SJed Brown 
7210c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
7220c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
7230c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7240c7d97c5SJed Brown 
7250c7d97c5SJed Brown   /* Local solution on R nodes */
7260c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
7270c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7280c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7290c7d97c5SJed Brown   if(pcbddc->prec_type) {
7300c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7310c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7320c7d97c5SJed Brown   }
7330c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
7340c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
7350c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7360c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7370c7d97c5SJed Brown   if(pcbddc->prec_type) {
7380c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7390c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7400c7d97c5SJed Brown   }
7410c7d97c5SJed Brown 
7420c7d97c5SJed Brown   /* Coarse solution */
7430c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
74453cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
7450c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7460c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7470c7d97c5SJed Brown 
7480c7d97c5SJed Brown   /* Sum contributions from two levels */
7490c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7500c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
751*da1bb401SStefano Zampini 
752*da1bb401SStefano Zampini   /* Apply partition of unity and sum boundary values */
753*da1bb401SStefano Zampini   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
7540c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
7550c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7560c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7570c7d97c5SJed Brown   PetscFunctionReturn(0);
7580c7d97c5SJed Brown }
7590c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7600c7d97c5SJed Brown #undef __FUNCT__
7610c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
76253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
7630c7d97c5SJed Brown {
7640c7d97c5SJed Brown   PetscErrorCode ierr;
7650c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
7660c7d97c5SJed Brown 
7670c7d97c5SJed Brown   PetscFunctionBegin;
76853cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
7690c7d97c5SJed Brown   if(pcbddc->n_constraints) {
7700c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
7710c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
7720c7d97c5SJed Brown   }
7730c7d97c5SJed Brown   PetscFunctionReturn(0);
7740c7d97c5SJed Brown }
7750c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7760c7d97c5SJed Brown #undef __FUNCT__
7770c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
77853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
7790c7d97c5SJed Brown {
7800c7d97c5SJed Brown   PetscErrorCode ierr;
7810c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
7820c7d97c5SJed Brown 
7830c7d97c5SJed Brown   PetscFunctionBegin;
7840c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
7850c7d97c5SJed Brown     case SCATTERS_BDDC:
7860c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
7870c7d97c5SJed Brown       break;
7880c7d97c5SJed Brown     case GATHERS_BDDC:
7890c7d97c5SJed Brown       break;
7900c7d97c5SJed Brown   }
7910c7d97c5SJed Brown   PetscFunctionReturn(0);
7920c7d97c5SJed Brown }
7930c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7940c7d97c5SJed Brown #undef __FUNCT__
7950c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
79653cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
7970c7d97c5SJed Brown {
7980c7d97c5SJed Brown   PetscErrorCode ierr;
7990c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
8000c7d97c5SJed Brown   PetscScalar*   array_to;
8010c7d97c5SJed Brown   PetscScalar*   array_from;
8020c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
8030c7d97c5SJed Brown   PetscInt i;
8040c7d97c5SJed Brown 
8050c7d97c5SJed Brown   PetscFunctionBegin;
8060c7d97c5SJed Brown 
8070c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
8080c7d97c5SJed Brown     case SCATTERS_BDDC:
8090c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
8100c7d97c5SJed Brown       break;
8110c7d97c5SJed Brown     case GATHERS_BDDC:
8120c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
8130c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
8140c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
8150c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
8160c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
81753cdbc3dSStefano Zampini             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);
8180c7d97c5SJed Brown             if(vec_to) {
8190c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
8200c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
8210c7d97c5SJed Brown             }
8220c7d97c5SJed Brown           } else {
8230c7d97c5SJed Brown             if(vec_from)
8240c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
8250c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
82653cdbc3dSStefano Zampini             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);
8270c7d97c5SJed Brown           }
8280c7d97c5SJed Brown           break;
8290c7d97c5SJed Brown         case REPLICATED_BDDC:
8300c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
83153cdbc3dSStefano Zampini             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);
8320c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
8330c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
8340c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
8350c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
8360c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
8370c7d97c5SJed Brown           }
8380c7d97c5SJed Brown           break;
83953cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
84053cdbc3dSStefano Zampini           break;
84153cdbc3dSStefano Zampini         case PARALLEL_BDDC:
84253cdbc3dSStefano Zampini           break;
8430c7d97c5SJed Brown       }
8440c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
8450c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
8460c7d97c5SJed Brown       break;
8470c7d97c5SJed Brown   }
8480c7d97c5SJed Brown   PetscFunctionReturn(0);
8490c7d97c5SJed Brown }
8500c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
851de534f79Sstefano_zampini #ifdef BDDC_USE_POD
852de534f79Sstefano_zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
8533b03a366Sstefano_zampini #define PETSC_MISSING_LAPACK_GESVD 1
854de534f79Sstefano_zampini #define UNDEF_PETSC_MISSING_LAPACK_GESVD 1
855de534f79Sstefano_zampini #endif
8563b03a366Sstefano_zampini #endif
8573b03a366Sstefano_zampini 
8583b03a366Sstefano_zampini #undef __FUNCT__
8593b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
8603b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
8613b03a366Sstefano_zampini {
8623b03a366Sstefano_zampini   PetscErrorCode ierr;
8633b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
8643b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8653b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
8663b03a366Sstefano_zampini   PetscInt       *nnz,*vertices,*is_indices;
8673b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
8683b03a366Sstefano_zampini   PetscInt       *temp_indices,*temp_indices_to_constraint;
8693b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
8703b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
8713b03a366Sstefano_zampini   PetscReal      quad_value;
8723b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
8733b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
8743b03a366Sstefano_zampini   IS             *used_IS;
8753b03a366Sstefano_zampini   const MatType  impMatType=MATSEQAIJ;
8763b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
8773b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
878fcda91b4SJed Brown   MatNullSpace   nearnullsp;
879fcda91b4SJed Brown   const Vec      *nearnullvecs;
8803b03a366Sstefano_zampini   Vec            *localnearnullsp;
8813b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
8823b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
883de534f79Sstefano_zampini   PetscBLASInt   Bone=1;
884de534f79Sstefano_zampini /* some ugly conditional declarations */
8853b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8863b03a366Sstefano_zampini   PetscScalar    dot_result;
8873b03a366Sstefano_zampini   PetscScalar    one=1.0,zero=0.0;
8883b03a366Sstefano_zampini   PetscInt       ii;
8893b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8903b03a366Sstefano_zampini   PetscScalar    val1,val2;
8913b03a366Sstefano_zampini #endif
8923b03a366Sstefano_zampini #else
8933b03a366Sstefano_zampini   PetscBLASInt   dummy_int;
8943b03a366Sstefano_zampini   PetscScalar    dummy_scalar;
8953b03a366Sstefano_zampini #endif
8963b03a366Sstefano_zampini 
8973b03a366Sstefano_zampini   PetscFunctionBegin;
8983b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
899fcda91b4SJed Brown   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
900fcda91b4SJed Brown   if (nearnullsp) {
901fcda91b4SJed Brown     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
9023b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
9033b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
9043b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
9053b03a366Sstefano_zampini   }
9063b03a366Sstefano_zampini   if(nnsp_has_cnst) {
9073b03a366Sstefano_zampini     nnsp_addone = 1;
9083b03a366Sstefano_zampini   }
9093b03a366Sstefano_zampini   /*
9103b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
9113b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
9123b03a366Sstefano_zampini        - temp_indices_to_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in local numbering) on which the constraint acts
9133b03a366Sstefano_zampini        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
9143b03a366Sstefano_zampini                                                                                                                                                          */
915*da1bb401SStefano Zampini 
9163b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
9173b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
918*da1bb401SStefano Zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
919*da1bb401SStefano Zampini   total_counts += n_vertices;
9203b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
9213b03a366Sstefano_zampini   total_counts = 0;
9223b03a366Sstefano_zampini   max_size_of_constraint = 0;
9233b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
9243b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
9253b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
9263b03a366Sstefano_zampini     } else {
9273b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
9283b03a366Sstefano_zampini     }
9293b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
9303b03a366Sstefano_zampini     total_counts += j;
9313b03a366Sstefano_zampini     if(j>max_size_of_constraint) max_size_of_constraint=j;
9323b03a366Sstefano_zampini   }
9333b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
934*da1bb401SStefano Zampini   total_counts += n_vertices;
9353b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
9363b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
9373b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
9383b03a366Sstefano_zampini   rwork = 0;
9393b03a366Sstefano_zampini   work = 0;
9403b03a366Sstefano_zampini   singular_vals = 0;
9413b03a366Sstefano_zampini   temp_basis = 0;
9423b03a366Sstefano_zampini   correlation_mat = 0;
9433b03a366Sstefano_zampini   if(!pcbddc->use_nnsp_true) {
9443b03a366Sstefano_zampini     PetscScalar temp_work;
9453b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
9463b03a366Sstefano_zampini     /* POD */
9473b03a366Sstefano_zampini     PetscInt max_n;
9483b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
9493b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
9503b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
9513b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
9523b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
9533b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9543b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
9553b03a366Sstefano_zampini #endif
9563b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
9573b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
9583b03a366Sstefano_zampini     lwork=-1;
9593b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9603b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
9613b03a366Sstefano_zampini #else
9623b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
9633b03a366Sstefano_zampini #endif
9643b03a366Sstefano_zampini #else /* on missing GESVD */
9653b03a366Sstefano_zampini     /* SVD */
9663b03a366Sstefano_zampini     PetscInt max_n,min_n;
9673b03a366Sstefano_zampini     max_n = max_size_of_constraint;
9683b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
9693b03a366Sstefano_zampini     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
9703b03a366Sstefano_zampini       min_n = max_size_of_constraint;
9713b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
9723b03a366Sstefano_zampini     }
9733b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
9743b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9753b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
9763b03a366Sstefano_zampini #endif
9773b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
9783b03a366Sstefano_zampini     lwork=-1;
9793b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
9803b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
9813b03a366Sstefano_zampini     dummy_int = Bs;
982670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
9833b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9843b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9853b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
9863b03a366Sstefano_zampini #else
9873b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9883b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
9893b03a366Sstefano_zampini #endif
9903b03a366Sstefano_zampini     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
991670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
9923b03a366Sstefano_zampini #endif
9933b03a366Sstefano_zampini     /* Allocate optimal workspace */
9943b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
9953b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
9963b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
9973b03a366Sstefano_zampini   }
9983b03a366Sstefano_zampini   /* get local part of global near null space vectors */
9993b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
10003b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) {
10013b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1002fcda91b4SJed Brown     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1003fcda91b4SJed Brown     ierr = VecScatterEnd  (matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10043b03a366Sstefano_zampini   }
10053b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
10063b03a366Sstefano_zampini   total_counts=0;
10073b03a366Sstefano_zampini   temp_indices[0]=0;
1008*da1bb401SStefano Zampini   /* vertices */
1009*da1bb401SStefano Zampini   PetscBool used_vertex;
1010*da1bb401SStefano Zampini   ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
1011*da1bb401SStefano Zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1012*da1bb401SStefano Zampini   if(nnsp_has_cnst) { /* consider all vertices */
1013*da1bb401SStefano Zampini     for(i=0;i<n_vertices;i++) {
1014*da1bb401SStefano Zampini       temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1015*da1bb401SStefano Zampini       temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1016*da1bb401SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1017*da1bb401SStefano Zampini       vertices[total_counts]=is_indices[i];
1018*da1bb401SStefano Zampini       total_counts++;
1019*da1bb401SStefano Zampini     }
1020*da1bb401SStefano Zampini   } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1021*da1bb401SStefano Zampini     for(i=0;i<n_vertices;i++) {
1022*da1bb401SStefano Zampini       used_vertex=PETSC_FALSE;
1023*da1bb401SStefano Zampini       k=0;
1024*da1bb401SStefano Zampini       while(!used_vertex && k<nnsp_size) {
1025*da1bb401SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1026*da1bb401SStefano Zampini         if(PetscAbsScalar(array_vector[is_indices[i]])>0.0) {
1027*da1bb401SStefano Zampini           temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1028*da1bb401SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1029*da1bb401SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1030*da1bb401SStefano Zampini           vertices[total_counts]=is_indices[i];
1031*da1bb401SStefano Zampini           total_counts++;
1032*da1bb401SStefano Zampini           used_vertex=PETSC_TRUE;
1033*da1bb401SStefano Zampini         }
1034*da1bb401SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1035*da1bb401SStefano Zampini         k++;
1036*da1bb401SStefano Zampini       }
1037*da1bb401SStefano Zampini     }
1038*da1bb401SStefano Zampini   }
1039*da1bb401SStefano Zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1040*da1bb401SStefano Zampini   n_vertices=total_counts;
1041*da1bb401SStefano Zampini   /* edges and faces */
10423b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
10433b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
10443b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
10453b03a366Sstefano_zampini     } else {
10463b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
10473b03a366Sstefano_zampini     }
10483b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
10493b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
10503b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
10513b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10523b03a366Sstefano_zampini     if(nnsp_has_cnst) {
10533b03a366Sstefano_zampini       temp_constraints++;
10543b03a366Sstefano_zampini       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
10553b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
10563b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
10573b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
10583b03a366Sstefano_zampini       }
10593b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
10603b03a366Sstefano_zampini       total_counts++;
10613b03a366Sstefano_zampini     }
10623b03a366Sstefano_zampini     for(k=0;k<nnsp_size;k++) {
10633b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
10643b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
10653b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
10663b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
10673b03a366Sstefano_zampini       }
10683b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1069de534f79Sstefano_zampini       quad_value = 1.0;
1070de534f79Sstefano_zampini       if( use_nnsp_true ) { /* check if array is null on the connected component in case use_nnsp_true has been requested */
1071de534f79Sstefano_zampini         Bs = PetscBLASIntCast(size_of_constraint);
1072de534f79Sstefano_zampini         quad_value = BLASasum_(&Bs,&temp_quadrature_constraint[temp_indices[total_counts]],&Bone);
1073de534f79Sstefano_zampini       }
1074de534f79Sstefano_zampini       if ( quad_value > 0.0 ) { /* keep indices and values */
1075de534f79Sstefano_zampini         temp_constraints++;
10763b03a366Sstefano_zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
10773b03a366Sstefano_zampini         total_counts++;
10783b03a366Sstefano_zampini       }
1079de534f79Sstefano_zampini     }
10803b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1081de534f79Sstefano_zampini     /* perform SVD on the constraint if use_nnsp_true has not be requested by the user */
10823b03a366Sstefano_zampini     if(!use_nnsp_true) {
1083de534f79Sstefano_zampini 
10843b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
10853b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
1086de534f79Sstefano_zampini 
10873b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
10883b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
10893b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
10903b03a366Sstefano_zampini       for(j=0;j<temp_constraints;j++) {
10913b03a366Sstefano_zampini         for(k=0;k<j+1;k++) {
10923b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
10933b03a366Sstefano_zampini           /* hand made complex dot product */
10943b03a366Sstefano_zampini           dot_result = 0.0;
10953b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
10963b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
10973b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
10983b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
10993b03a366Sstefano_zampini           }
11003b03a366Sstefano_zampini #else
11013b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
11023b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
11033b03a366Sstefano_zampini #endif
11043b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
11053b03a366Sstefano_zampini         }
11063b03a366Sstefano_zampini       }
11073b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
11083b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
11093b03a366Sstefano_zampini #else
11103b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
11113b03a366Sstefano_zampini #endif
11123b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
11133b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
11143b03a366Sstefano_zampini       j=0;
11153b03a366Sstefano_zampini       while( j < Bt && singular_vals[j] < tol) j++;
11163b03a366Sstefano_zampini       total_counts=total_counts-j;
11173b03a366Sstefano_zampini       if(j<temp_constraints) {
11183b03a366Sstefano_zampini         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
11193b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
11203b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
11213b03a366Sstefano_zampini         for(k=0;k<Bt-j;k++) {
11223b03a366Sstefano_zampini           for(ii=0;ii<size_of_constraint;ii++) {
11233b03a366Sstefano_zampini             temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[Bt-1-k]*temp_basis[(Bt-1-k)*size_of_constraint+ii];
11243b03a366Sstefano_zampini           }
11253b03a366Sstefano_zampini         }
11263b03a366Sstefano_zampini       }
1127de534f79Sstefano_zampini 
11283b03a366Sstefano_zampini #else  /* on missing GESVD */
1129de534f79Sstefano_zampini 
11303b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
11313b03a366Sstefano_zampini       if(min_n > size_of_constraint) min_n = size_of_constraint;
11323b03a366Sstefano_zampini       dummy_int = Bs;
1133670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
11343b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
11353b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
11363b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
11373b03a366Sstefano_zampini #else
11383b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
11393b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
11403b03a366Sstefano_zampini #endif
11413b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
1142670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
11433b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
11443b03a366Sstefano_zampini       j=0;
11453b03a366Sstefano_zampini       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
11463b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
1147de534f79Sstefano_zampini 
11483b03a366Sstefano_zampini #endif
11493b03a366Sstefano_zampini     }
11503b03a366Sstefano_zampini   }
1151*da1bb401SStefano Zampini   n_constraints=total_counts-n_vertices;
1152*da1bb401SStefano Zampini   local_primal_size = total_counts;
11533b03a366Sstefano_zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
11543b03a366Sstefano_zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
11553b03a366Sstefano_zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
11563b03a366Sstefano_zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
1157*da1bb401SStefano Zampini   for(i=0;i<local_primal_size;i++) {
1158*da1bb401SStefano Zampini     nnz[i]=temp_indices[i+1]-temp_indices[i];
1159*da1bb401SStefano Zampini   }
11603b03a366Sstefano_zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
1161*da1bb401SStefano Zampini   for(i=0;i<local_primal_size;i++) {
11623b03a366Sstefano_zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1163*da1bb401SStefano Zampini     ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&i,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
11643b03a366Sstefano_zampini   }
11653b03a366Sstefano_zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11663b03a366Sstefano_zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11673b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
11683b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
11693b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
1170*da1bb401SStefano Zampini   pcbddc->local_primal_size = local_primal_size;
11713b03a366Sstefano_zampini   /* free workspace no longer needed */
11723b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
11733b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
11743b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
11753b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
11763b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
11773b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
11783b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
11793b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
11803b03a366Sstefano_zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
1181*da1bb401SStefano Zampini   for(k=0;k<nnsp_size;k++) {
1182*da1bb401SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1183*da1bb401SStefano Zampini   }
11843b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
11853b03a366Sstefano_zampini   PetscFunctionReturn(0);
11863b03a366Sstefano_zampini }
1187de534f79Sstefano_zampini #ifdef UNDEF_PETSC_MISSING_LAPACK_GESVD
11883b03a366Sstefano_zampini #undef PETSC_MISSING_LAPACK_GESVD
11893b03a366Sstefano_zampini #endif
11903b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
11910c7d97c5SJed Brown #undef __FUNCT__
11920c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
119353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
11940c7d97c5SJed Brown {
11950c7d97c5SJed Brown   PetscErrorCode  ierr;
11960c7d97c5SJed Brown 
11970c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
11980c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
11990c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
12000c7d97c5SJed Brown   IS                is_R_local;
12010c7d97c5SJed Brown   IS                is_V_local;
12020c7d97c5SJed Brown   IS                is_C_local;
12030c7d97c5SJed Brown   IS                is_aux1;
12040c7d97c5SJed Brown   IS                is_aux2;
12050c7d97c5SJed Brown   const VecType     impVecType;
12060c7d97c5SJed Brown   const MatType     impMatType;
12070c7d97c5SJed Brown   PetscInt          n_R=0;
12080c7d97c5SJed Brown   PetscInt          n_D=0;
12090c7d97c5SJed Brown   PetscInt          n_B=0;
12100c7d97c5SJed Brown   PetscScalar       zero=0.0;
12110c7d97c5SJed Brown   PetscScalar       one=1.0;
12120c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
12130c7d97c5SJed Brown   PetscScalar*      array;
12140c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
12150c7d97c5SJed Brown   PetscInt          *idx_R_local;
12160c7d97c5SJed Brown   PetscInt          *idx_V_B;
12170c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
12180c7d97c5SJed Brown   PetscScalar       *constraints_errors;
12190c7d97c5SJed Brown   /* auxiliary indices */
1220*da1bb401SStefano Zampini   PetscInt i,j;
1221e269702eSStefano Zampini   /* for verbose output of bddc */
1222e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1223e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1224a0ba757dSStefano Zampini   /* for counting coarse dofs */
12253b03a366Sstefano_zampini   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
12263b03a366Sstefano_zampini   PetscInt          size_of_constraint;
12273b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
12283b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1229*da1bb401SStefano Zampini   PetscInt          *vertices;
12300c7d97c5SJed Brown 
12310c7d97c5SJed Brown   PetscFunctionBegin;
12320c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
12330c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
12343b03a366Sstefano_zampini 
1235*da1bb401SStefano Zampini   /* get vertex indices from constraint matrix */
1236*da1bb401SStefano Zampini   ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
1237*da1bb401SStefano Zampini   j=0;
1238*da1bb401SStefano Zampini   for(i=0;i<pcbddc->local_primal_size;i++) {
1239*da1bb401SStefano Zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1240*da1bb401SStefano Zampini     if(size_of_constraint == 1) {
1241*da1bb401SStefano Zampini       vertices[j]=row_cmat_indices[0];
1242*da1bb401SStefano Zampini       j++;
1243a0ba757dSStefano Zampini     }
1244*da1bb401SStefano Zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1245a0ba757dSStefano Zampini   }
1246a0ba757dSStefano Zampini 
12470c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
12480c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
12490c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12503b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
12513b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
12520c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
12530c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1254e269702eSStefano Zampini   if(dbg_flag) {
12550c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12560c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12570c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
12580c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
12593b03a366Sstefano_zampini     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);
12600c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12610c7d97c5SJed Brown   }
12620c7d97c5SJed Brown   /* Allocate needed vectors */
12630c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
12640c7d97c5SJed Brown   impMatType = MATSEQDENSE;
12650c7d97c5SJed Brown   impVecType = VECSEQ;
12660c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
12670c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
12680c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
12690c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1270d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
12710c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
12720c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
12730c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
12740c7d97c5SJed Brown 
12750c7d97c5SJed Brown   /* Creating some index sets needed  */
12760c7d97c5SJed Brown   /* For submatrices */
1277*da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
12783b03a366Sstefano_zampini   if(n_vertices)    {
1279*da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_OWN_POINTER,&is_V_local);CHKERRQ(ierr);
12803b03a366Sstefano_zampini   }
1281*da1bb401SStefano Zampini   if(n_constraints) {
1282*da1bb401SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
1283*da1bb401SStefano Zampini   }
1284*da1bb401SStefano Zampini 
12850c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
12860c7d97c5SJed Brown   {
12870c7d97c5SJed Brown     PetscInt   *aux_array1;
12880c7d97c5SJed Brown     PetscInt   *aux_array2;
12890c7d97c5SJed Brown 
12903b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
12913b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
12920c7d97c5SJed Brown 
1293d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
12940c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12950c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12960c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12970c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12980c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12990c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13000c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1301*da1bb401SStefano Zampini     for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[j] = i; j++; } }
13020c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1303*da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
13040c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1305*da1bb401SStefano Zampini     for (i=0, j=0; i<n_B; i++) { if (array[i] > one) { aux_array2[j] = i; j++; } }
13063828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1307*da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
13080c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
13090c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
13100c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
13110c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
13120c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
13130c7d97c5SJed Brown 
1314e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
13150c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
13160c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1317*da1bb401SStefano Zampini       for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[j] = i; j++; } }
13180c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1319*da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
13200c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
13210c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
13220c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
13230c7d97c5SJed Brown     }
13240c7d97c5SJed Brown   }
13250c7d97c5SJed Brown 
13260c7d97c5SJed Brown   /* vertices in boundary numbering */
13273b03a366Sstefano_zampini   if(n_vertices) {
1328d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
13290c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13303b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
13310c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1332d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1333d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13343b03a366Sstefano_zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
13350c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13363b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) {
1337*da1bb401SStefano Zampini       j=0;
1338*da1bb401SStefano Zampini       while (array[j] != i ) {j++;}
1339*da1bb401SStefano Zampini       idx_V_B[i]=j;
13400c7d97c5SJed Brown     }
13410c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13420c7d97c5SJed Brown   }
13430c7d97c5SJed Brown 
13440c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
13450c7d97c5SJed Brown   {
13460c7d97c5SJed Brown     Mat  A_RR;
134753cdbc3dSStefano Zampini     PC   pc_temp;
13480c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
134953cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
135053cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
135153cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
135253cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1353*da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
13540c7d97c5SJed Brown     /* default */
135553cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
135653cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13570c7d97c5SJed Brown     /* Allow user's customization */
135853cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
135953cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
136053cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1361*da1bb401SStefano Zampini     if(pcbddc->dbg_flag) ierr = KSPView(pcbddc->ksp_D,PETSC_VIEWER_STDOUT_SELF);
13620c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
13630c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
136453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
136553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
136653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
136753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1368*da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
13690c7d97c5SJed Brown     /* default */
137053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
137153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13720c7d97c5SJed Brown     /* Allow user's customization */
137353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
137453cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
137553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1376*da1bb401SStefano Zampini     if(pcbddc->dbg_flag) ierr = KSPView(pcbddc->ksp_R,PETSC_VIEWER_STDOUT_SELF);
1377a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1378e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
13790c7d97c5SJed Brown       Vec temp_vec;
13800c7d97c5SJed Brown       PetscScalar value;
13810c7d97c5SJed Brown 
1382a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1383a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1384a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1385a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1386a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1387a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1388a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1389a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1390a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1391a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1392a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1393d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1394d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1395d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1396d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1397d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1398d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1399e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
14000c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1401d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14020c7d97c5SJed Brown     }
14030c7d97c5SJed Brown     /* free Neumann problem's matrix */
14040c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
14050c7d97c5SJed Brown   }
14060c7d97c5SJed Brown 
14070c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
14080c7d97c5SJed Brown   {
14090c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
14100c7d97c5SJed Brown     Mat          M1,M2;
14110c7d97c5SJed Brown     Mat          C_CR;
14123b03a366Sstefano_zampini     Mat          AUXMAT;
14130c7d97c5SJed Brown     Vec          vec1_C;
14140c7d97c5SJed Brown     Vec          vec2_C;
14150c7d97c5SJed Brown     Vec          vec1_V;
14160c7d97c5SJed Brown     Vec          vec2_V;
14170c7d97c5SJed Brown     PetscInt     *nnz;
14180c7d97c5SJed Brown     PetscInt     *auxindices;
141953cdbc3dSStefano Zampini     PetscInt     index;
14200c7d97c5SJed Brown     PetscScalar* array2;
14210c7d97c5SJed Brown     MatFactorInfo matinfo;
14220c7d97c5SJed Brown 
14230c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
14240c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
14250c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
14260c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
14270c7d97c5SJed Brown 
14280c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
14293b03a366Sstefano_zampini     if(n_vertices) {
14300c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
14313b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
14320c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
14330c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
14340c7d97c5SJed Brown     }
14350c7d97c5SJed Brown     if(pcbddc->n_constraints) {
14360c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
14370c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
14380c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
14390c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
14400c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
14410c7d97c5SJed Brown     }
14420c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14433b03a366Sstefano_zampini     if(n_constraints) {
14440c7d97c5SJed Brown       /* some work vectors */
14450c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14463b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14470c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14483b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
14490c7d97c5SJed Brown 
14500c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14513b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
1452d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
14533b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
14543b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
14550c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14563b03a366Sstefano_zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14573b03a366Sstefano_zampini         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
14583b03a366Sstefano_zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14590c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14600c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
14610c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14620c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14633b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
146453cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14653b03a366Sstefano_zampini         /* Set values */
14660c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14673b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14680c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14690c7d97c5SJed Brown       }
14700c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14710c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14720c7d97c5SJed Brown 
14730c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
14743b03a366Sstefano_zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
14750c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
14760c7d97c5SJed Brown 
14770c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14780c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1479d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14803b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14810c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14820c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14830c7d97c5SJed Brown 
14843b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1485d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14863b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14870c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14883b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
14893b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
14900c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14910c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14920c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14930c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14940c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14950c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14960c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14973b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14980c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14990c7d97c5SJed Brown       }
15000c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15010c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15020c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
15030c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
15040c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
15050c7d97c5SJed Brown 
15060c7d97c5SJed Brown     }
15070c7d97c5SJed Brown 
15080c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
15093b03a366Sstefano_zampini     if(n_vertices){
15100c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
15110c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
15120c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
15130c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1514d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
15153b03a366Sstefano_zampini       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
15160c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
15173b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
15183b03a366Sstefano_zampini       for(i=0;i<n_vertices;i++) {
15190c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15200c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15210c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15220c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15230c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
152453cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
15250c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15263b03a366Sstefano_zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15270c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15280c7d97c5SJed Brown       }
15290c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15300c7d97c5SJed Brown       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15310c7d97c5SJed Brown     }
15320c7d97c5SJed Brown 
15330c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1534d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
15350c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
15360c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
15373b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1538e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1539d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
15400c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
15410c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
15423b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
15430c7d97c5SJed Brown     }
15440c7d97c5SJed Brown 
1545e269702eSStefano Zampini     if(dbg_flag) {
15460c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
15470c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
15480c7d97c5SJed Brown     }
15493b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15500c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15510c7d97c5SJed Brown 
15520c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15533b03a366Sstefano_zampini     for(i=0;i<n_vertices;i++){
15540c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15550c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15560c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15570c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15580c7d97c5SJed Brown       /* solution of saddle point problem */
15590c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15600c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15613b03a366Sstefano_zampini       if(n_constraints) {
15620c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15630c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15640c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15650c7d97c5SJed Brown       }
15660c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15670c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15680c7d97c5SJed Brown 
15690c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15700c7d97c5SJed Brown       /* coarse basis functions */
15710c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15720c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15730c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15740c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15753b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15760c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15770c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1578e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
15790c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15800c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15810c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15823b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15830c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15840c7d97c5SJed Brown       }
15850c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15860c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1587*da1bb401SStefano Zampini       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } /* WARNING -> column major ordering */
15880c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15893b03a366Sstefano_zampini       if(n_constraints) {
15900c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1591*da1bb401SStefano Zampini         for(j=0;j<n_constraints;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j+n_vertices] = array[j]; } /* WARNING -> column major ordering */
15920c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15930c7d97c5SJed Brown       }
15940c7d97c5SJed Brown 
1595e269702eSStefano Zampini       if( dbg_flag ) {
15960c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1597d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15980c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15990c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16000c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
16013b03a366Sstefano_zampini         array[ vertices[i] ] = one;
16020c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16030c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16040c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1605d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16060c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16070c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16083b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
16090c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16103b03a366Sstefano_zampini         if(n_constraints) {
16110c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16123b03a366Sstefano_zampini           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
16130c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16140c7d97c5SJed Brown         }
16150c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16160c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
16170c7d97c5SJed Brown         /* check saddle point solution */
16180c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16193b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
16203b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
16213b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16220c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16233b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
16240c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16253b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
16260c7d97c5SJed Brown       }
16270c7d97c5SJed Brown     }
16280c7d97c5SJed Brown 
16293b03a366Sstefano_zampini     for(i=0;i<n_constraints;i++){
1630d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
16310c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
16320c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
16330c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
16340c7d97c5SJed Brown       /* solution of saddle point problem */
16350c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
16360c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
16370c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
16383b03a366Sstefano_zampini       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
16390c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
16400c7d97c5SJed Brown       /* coarse basis functions */
16413b03a366Sstefano_zampini       index=i+n_vertices;
16420c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
16430c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16440c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16450c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
164653cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16470c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1648e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
16490c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16500c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16510c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
165253cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16530c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16540c7d97c5SJed Brown       }
16550c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16563b03a366Sstefano_zampini       if(n_vertices) {
16570c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1658*da1bb401SStefano Zampini         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} /* WARNING -> column major ordering */
16590c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16600c7d97c5SJed Brown       }
16610c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1662*da1bb401SStefano Zampini       for(j=0;j<n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+n_vertices]=array[j];} /* WARNING -> column major ordering */
16630c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16640c7d97c5SJed Brown 
1665e269702eSStefano Zampini       if( dbg_flag ) {
16660c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
166753cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16680c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16690c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16700c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
16710c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16720c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16730c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
167453cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16750c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16763b03a366Sstefano_zampini         if( n_vertices) {
16770c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16783b03a366Sstefano_zampini           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
16790c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16800c7d97c5SJed Brown         }
16810c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16823b03a366Sstefano_zampini         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16830c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16840c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16850c7d97c5SJed Brown         /* check saddle point solution */
16860c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16873b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
168853cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16893b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16900c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
169153cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16920c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
169353cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16940c7d97c5SJed Brown       }
16950c7d97c5SJed Brown     }
16960c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16970c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1698e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
16990c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17000c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17010c7d97c5SJed Brown     }
17020c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
17030c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
17049d2fce94SStefano Zampini     if(dbg_flag) {
17050c7d97c5SJed Brown 
17060c7d97c5SJed Brown       Mat coarse_sub_mat;
17070c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
17080c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1709a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
17100c7d97c5SJed Brown       PetscScalar      value;
17110c7d97c5SJed Brown 
1712c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1713c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1714c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1715c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1716c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1717c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1718c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1719c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
17200c7d97c5SJed Brown 
1721*da1bb401SStefano Zampini       /*PetscViewer view_out;
1722*da1bb401SStefano Zampini       PetscMPIInt myrank;
1723*da1bb401SStefano Zampini       char filename[256];
1724*da1bb401SStefano Zampini       MPI_Comm_rank(((PetscObject)pc)->comm,&myrank);
1725*da1bb401SStefano Zampini       sprintf(filename,"coarsesubmat_%04d.m",myrank);
1726*da1bb401SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&view_out);CHKERRQ(ierr);
1727*da1bb401SStefano Zampini       ierr = PetscViewerSetFormat(view_out,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1728*da1bb401SStefano Zampini       ierr = MatView(coarse_sub_mat,view_out);CHKERRQ(ierr);
1729*da1bb401SStefano Zampini       ierr = PetscViewerDestroy(&view_out);CHKERRQ(ierr);*/
1730*da1bb401SStefano Zampini 
17310c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
17320c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
17330c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
173453cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
173553cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
173653cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1737c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
173853cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173953cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1740c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
174153cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
174253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174653cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
17470c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
17480c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
17490c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
17500c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
175153cdbc3dSStefano Zampini       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); }
17520c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
175353cdbc3dSStefano Zampini       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); }
17540c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
175553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
175653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
175753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
175853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
175953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
176053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
176153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
176253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
176353cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
176453cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
176553cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
17660c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
17670c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
17680c7d97c5SJed Brown     }
17690c7d97c5SJed Brown 
17700c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
17710c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
17720c7d97c5SJed Brown     /* free memory */
17730c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
17740c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
17750c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
17763b03a366Sstefano_zampini     if(n_vertices) {
17770c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
17780c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
17790c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
17800c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
17810c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
17820c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
17830c7d97c5SJed Brown     }
17840c7d97c5SJed Brown     if(pcbddc->n_constraints) {
17850c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
17860c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
17870c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
17880c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
17890c7d97c5SJed Brown     }
17900c7d97c5SJed Brown   }
17910c7d97c5SJed Brown   /* free memory */
17923b03a366Sstefano_zampini   if(n_vertices) {
17930c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17940c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17950c7d97c5SJed Brown   }
17960c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
17970c7d97c5SJed Brown 
17980c7d97c5SJed Brown   PetscFunctionReturn(0);
17990c7d97c5SJed Brown }
18000c7d97c5SJed Brown 
18010c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
18020c7d97c5SJed Brown 
18030c7d97c5SJed Brown #undef __FUNCT__
18040c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
180553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
18060c7d97c5SJed Brown {
18070c7d97c5SJed Brown 
18080c7d97c5SJed Brown 
18090c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
18100c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
18110c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
18120c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
18130c7d97c5SJed Brown   MPI_Comm  coarse_comm;
18140c7d97c5SJed Brown 
18150c7d97c5SJed Brown   /* common to all choiches */
18160c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
18170c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
18180c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
18190c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
18200c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
18210c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
18220c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
18230c7d97c5SJed Brown   PetscMPIInt master_proc=0;
18240c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
18250c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
18260c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
18270c7d97c5SJed Brown   PetscMPIInt count_recv=0;
18280c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
18290c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
18300c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
18310c7d97c5SJed Brown   /* some other variables */
18320c7d97c5SJed Brown   PetscErrorCode ierr;
18330c7d97c5SJed Brown   const MatType coarse_mat_type;
18340c7d97c5SJed Brown   const PCType  coarse_pc_type;
183553cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
183653cdbc3dSStefano Zampini   PC pc_temp;
18370c7d97c5SJed Brown   PetscInt i,j,k,bs;
18383b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1839e269702eSStefano Zampini   /* verbose output viewer */
1840e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1841e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
18420c7d97c5SJed Brown 
18430c7d97c5SJed Brown   PetscFunctionBegin;
18440c7d97c5SJed Brown 
18450c7d97c5SJed Brown   ins_local_primal_indices = 0;
18460c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
18470c7d97c5SJed Brown   localsizes2              = 0;
18480c7d97c5SJed Brown   localdispl2              = 0;
18490c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
18500c7d97c5SJed Brown   coarse_ISLG              = 0;
18510c7d97c5SJed Brown 
185253cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
185353cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
18540c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
18550c7d97c5SJed Brown 
1856beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1857beed3852SStefano Zampini   {
1858a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1859beed3852SStefano Zampini     PetscScalar    *array;
1860beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1861beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1862beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1863beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1864beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1865*da1bb401SStefano Zampini     PetscInt       *row_cmat_indices;
18663b03a366Sstefano_zampini     PetscInt       size_of_constraint;
1867*da1bb401SStefano Zampini     PetscScalar    coarsesum;
1868beed3852SStefano Zampini 
1869beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1870beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1871beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1872beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1873beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
18745619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1875beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1876beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1877beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1878beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1879beed3852SStefano Zampini     }
18805619798eSStefano Zampini     if(rank_prec_comm == 0) {
1881beed3852SStefano Zampini       /* allocate some auxiliary space */
1882beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1883beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1884beed3852SStefano Zampini     }
1885beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1886beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1887beed3852SStefano Zampini 
1888*da1bb401SStefano Zampini     /* First let's count coarse dofs.
1889beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1890beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1891beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
18923b03a366Sstefano_zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1893beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1894beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1895*da1bb401SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1896*da1bb401SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
18973b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
18983b03a366Sstefano_zampini         k = row_cmat_indices[j];
1899beed3852SStefano Zampini         if( array[k] == zero ) {
1900beed3852SStefano Zampini           array[k] = one;
1901*da1bb401SStefano Zampini           auxlocal_primal[i] = k;
1902beed3852SStefano Zampini           break;
1903beed3852SStefano Zampini         }
1904beed3852SStefano Zampini       }
1905*da1bb401SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1906beed3852SStefano Zampini     }
1907beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1908*da1bb401SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1909*da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1910*da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1911*da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1912*da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1913*da1bb401SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1914*da1bb401SStefano Zampini     for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1915*da1bb401SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1916*da1bb401SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1917*da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1918*da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1919*da1bb401SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1920*da1bb401SStefano Zampini     pcbddc->coarse_size = (PetscInt) coarsesum;
1921a0ba757dSStefano Zampini 
1922beed3852SStefano Zampini     /* Now assign them a global numbering */
1923beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1924beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1925beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1926beed3852SStefano Zampini     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);
1927beed3852SStefano Zampini 
1928beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1929beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1930beed3852SStefano Zampini     if(rank_prec_comm==0) {
1931beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1932beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1933beed3852SStefano Zampini       k=1;
1934beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1935beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1936beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1937beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1938beed3852SStefano Zampini           k++;
1939beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1940beed3852SStefano Zampini         }
1941beed3852SStefano Zampini       }
1942beed3852SStefano Zampini     } else {
1943beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1944beed3852SStefano Zampini     }
19455619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1946beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1947beed3852SStefano Zampini 
1948beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1949beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1950beed3852SStefano Zampini       k=0;
1951beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1952beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1953beed3852SStefano Zampini     }
1954e269702eSStefano Zampini     if(dbg_flag) {
1955e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1956*da1bb401SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
1957e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1958e269702eSStefano Zampini     }
1959beed3852SStefano Zampini     /* free allocated memory */
1960beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1961beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1962beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1963e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1964beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1965beed3852SStefano Zampini     }
1966e269702eSStefano Zampini   }
1967beed3852SStefano Zampini 
19680c7d97c5SJed Brown   /* adapt coarse problem type */
19690c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
19700c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
19710c7d97c5SJed Brown 
19720c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
19730c7d97c5SJed Brown 
1974*da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
19750c7d97c5SJed Brown     {
19760c7d97c5SJed Brown       /* we need additional variables */
19770c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
19780c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
19790c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
19800c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
19810c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
19820c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
19830c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
19840c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
19850c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
19860c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
19870c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
19880c7d97c5SJed Brown       MetisInt    *faces_adjncy;
19890c7d97c5SJed Brown       MetisInt    *faces_xadj;
19900c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
19910c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
19920c7d97c5SJed Brown       PetscInt    *array_int;
19930c7d97c5SJed Brown       PetscMPIInt my_faces=0;
19940c7d97c5SJed Brown       PetscMPIInt total_faces=0;
19953828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
19960c7d97c5SJed Brown 
19970c7d97c5SJed Brown       /* define some quantities */
19980c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
19990c7d97c5SJed Brown       coarse_mat_type = MATIS;
20000c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
20016c9de887SHong Zhang       coarse_ksp_type  = KSPCHEBYSHEV;
20020c7d97c5SJed Brown 
20030c7d97c5SJed Brown       /* details of coarse decomposition */
20040c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
20050c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
20063828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
20073828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
20083828260eSStefano Zampini 
2009*da1bb401SStefano Zampini       /*printf("Coarse algorithm details: \n");
2010*da1bb401SStefano Zampini       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));*/
20110c7d97c5SJed Brown 
20120c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
20130c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
20143828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
20150c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
20160c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20170c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
20180c7d97c5SJed Brown         }
20190c7d97c5SJed Brown       }
20200c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20210c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20220c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20230c7d97c5SJed Brown             my_faces++;
20240c7d97c5SJed Brown             break;
20250c7d97c5SJed Brown           }
20260c7d97c5SJed Brown         }
20270c7d97c5SJed Brown       }
20280c7d97c5SJed Brown 
202953cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
20300c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
20310c7d97c5SJed Brown       my_faces=0;
20320c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20330c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20340c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20350c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
20360c7d97c5SJed Brown             my_faces++;
20370c7d97c5SJed Brown             break;
20380c7d97c5SJed Brown           }
20390c7d97c5SJed Brown         }
20400c7d97c5SJed Brown       }
20410c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20420c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
20430c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
20440c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
20450c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
20460c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
20470c7d97c5SJed Brown       }
204853cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
20490c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20500c7d97c5SJed Brown         faces_xadj[0]=0;
20510c7d97c5SJed Brown         faces_displacements[0]=0;
20520c7d97c5SJed Brown         j=0;
20530c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
20540c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
20550c7d97c5SJed Brown           if(number_of_faces[i-1]) {
20560c7d97c5SJed Brown             j++;
20570c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
20580c7d97c5SJed Brown           }
20590c7d97c5SJed Brown         }
2060*da1bb401SStefano Zampini         /*printf("The J I count is %d and should be %d\n",j,n_subdomains);
2061*da1bb401SStefano Zampini         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);*/
20620c7d97c5SJed Brown       }
206353cdbc3dSStefano Zampini       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);
20640c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
20650c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
20660c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20673828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
2068*da1bb401SStefano Zampini         /*printf("This is the face connectivity (actual ranks)\n");
20690c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
20700c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
20710c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
20720c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
20730c7d97c5SJed Brown           printf("\n");
2074*da1bb401SStefano Zampini         }*/
20750c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
20760c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
20770c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
20780c7d97c5SJed Brown       }
20790c7d97c5SJed Brown 
20800c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
20810c7d97c5SJed Brown 
20823828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
20833828260eSStefano Zampini 
20840c7d97c5SJed Brown         ncon=1;
20850c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
20860c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
20870c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
20880c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
20890c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
20900c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
20910c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
20920c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
20933828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
20943828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
20953828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
20960c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20973828260eSStefano Zampini         } else {
20983828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20993828260eSStefano Zampini         }
21000c7d97c5SJed Brown         if(ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetupCoarseEnvironment\n",ierr);
21010c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
21020c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
21030c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
21040c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
21053828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
21063828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
21070c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
21080c7d97c5SJed Brown       }
21090c7d97c5SJed Brown 
21100c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
21110c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2112*da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2113*da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
21140c7d97c5SJed Brown       }
2115*da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2116*da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
211753cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
21180c7d97c5SJed Brown 
21190c7d97c5SJed Brown       if( coarse_color == 0 ) {
212053cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
212153cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2122*da1bb401SStefano Zampini         /*printf("Details of coarse comm\n");
21233828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
2124*da1bb401SStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);*/
21250c7d97c5SJed Brown       } else {
21260c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
21270c7d97c5SJed Brown       }
21280c7d97c5SJed Brown 
21290c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
21300c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
21310c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
2132*da1bb401SStefano Zampini         /*ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
2133*da1bb401SStefano Zampini           ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);*/
21340c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
21350c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
21360c7d97c5SJed Brown         /* some initializations */
21370c7d97c5SJed Brown         displacements_recv[0]=0;
2138*da1bb401SStefano Zampini         /* PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero */
21390c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
21400c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
21413828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
21420c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
21430c7d97c5SJed Brown               total_count_recv[j]++;
21440c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
21450c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
21460c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
21470c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
21480c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
21493828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
21500c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
21510c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
21523828260eSStefano Zampini               total_count_recv[j]+=1;
21530c7d97c5SJed Brown             }
21540c7d97c5SJed Brown           }
21550c7d97c5SJed Brown         }
2156*da1bb401SStefano Zampini         /*for(j=0;j<size_coarse_comm;j++) {
21573828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
21583828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
21593828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
21603828260eSStefano Zampini           }
21613828260eSStefano Zampini           printf("\n");
2162*da1bb401SStefano Zampini         }*/
21630c7d97c5SJed Brown 
21640c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
21653828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
2166*da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
21670c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
21683828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
21693828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
21703828260eSStefano Zampini           } else {
21713828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
21723828260eSStefano Zampini           }
2173*da1bb401SStefano Zampini         printf("\n");*/
21740c7d97c5SJed Brown       }
21750c7d97c5SJed Brown 
21760c7d97c5SJed Brown       /* Scatter new decomposition for send details */
217753cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21780c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
21790c7d97c5SJed Brown       if( coarse_color == 0) {
218053cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21810c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
218253cdbc3dSStefano Zampini         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);
21830c7d97c5SJed Brown       }
21840c7d97c5SJed Brown 
2185*da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2186*da1bb401SStefano Zampini       if(coarse_color == 0) {
2187*da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2188*da1bb401SStefano Zampini         for(i=0;i<count_recv;i++)
2189*da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2190*da1bb401SStefano Zampini         printf("\n");
2191*da1bb401SStefano Zampini       }*/
21920c7d97c5SJed Brown 
21930c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
2194*da1bb401SStefano Zampini         /*ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2195*da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
2196*da1bb401SStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);*/
21970c7d97c5SJed Brown         free(coarse_subdivision);
21980c7d97c5SJed Brown         free(total_count_recv);
21990c7d97c5SJed Brown         free(total_ranks_recv);
22000c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
22010c7d97c5SJed Brown       }
22020c7d97c5SJed Brown       break;
22030c7d97c5SJed Brown     }
22040c7d97c5SJed Brown 
22050c7d97c5SJed Brown     case(REPLICATED_BDDC):
22060c7d97c5SJed Brown 
22070c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22080c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22090c7d97c5SJed Brown       coarse_pc_type  = PCLU;
221053cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22110c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22120c7d97c5SJed Brown       active_rank = rank_prec_comm;
22130c7d97c5SJed Brown       break;
22140c7d97c5SJed Brown 
22150c7d97c5SJed Brown     case(PARALLEL_BDDC):
22160c7d97c5SJed Brown 
22170c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
22180c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
22190c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
222053cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22210c7d97c5SJed Brown       coarse_comm = prec_comm;
22220c7d97c5SJed Brown       active_rank = rank_prec_comm;
22230c7d97c5SJed Brown       break;
22240c7d97c5SJed Brown 
22250c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
22260c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22270c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22280c7d97c5SJed Brown       coarse_pc_type = PCLU;
222953cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22300c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22310c7d97c5SJed Brown       active_rank = master_proc;
22320c7d97c5SJed Brown       break;
22330c7d97c5SJed Brown   }
22340c7d97c5SJed Brown 
22350c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
22360c7d97c5SJed Brown 
22370c7d97c5SJed Brown     case(SCATTERS_BDDC):
22380c7d97c5SJed Brown       {
22390c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
22400c7d97c5SJed Brown 
22410c7d97c5SJed Brown           PetscMPIInt send_size;
22420c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
22430c7d97c5SJed Brown           PetscInt    ii,jj;
22440c7d97c5SJed Brown           MPI_Request *requests;
22450c7d97c5SJed Brown 
22460c7d97c5SJed Brown           /* allocate auxiliary space */
22475619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
22485619798eSStefano Zampini           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);
22490c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
22500c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
22510c7d97c5SJed Brown           /* allocate stuffs for message massing */
22520c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
22530c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
22540c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
22550c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
22560c7d97c5SJed Brown           /* fill up quantities */
22570c7d97c5SJed Brown           j=0;
22580c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
22590c7d97c5SJed Brown             ii = ranks_recv[i];
22600c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
22610c7d97c5SJed Brown             localdispl2[i]=j;
22620c7d97c5SJed Brown             j+=localsizes2[i];
22630c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
2264*da1bb401SStefano Zampini             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 */
22650c7d97c5SJed Brown           }
2266*da1bb401SStefano Zampini           /*printf("aux_ins_indices 1\n");
2267*da1bb401SStefano Zampini           for(i=0;i<pcbddc->coarse_size;i++)
2268*da1bb401SStefano Zampini             printf("%d ",aux_ins_indices[i]);
2269*da1bb401SStefano Zampini           printf("\n");*/
22700c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
22710c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
22720c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
22730c7d97c5SJed Brown           ins_local_primal_size=0;
22740c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22750c7d97c5SJed Brown             if(aux_ins_indices[i])
22760c7d97c5SJed Brown               ins_local_primal_size++;
22770c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
22780c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
22790c7d97c5SJed Brown           j=0;
22800c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22810c7d97c5SJed Brown             if(aux_ins_indices[i])
22820c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
22830c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
22840c7d97c5SJed Brown           j=0;
22850c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
22860c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
22870c7d97c5SJed Brown               aux_ins_indices[i]=-1;
22880c7d97c5SJed Brown             } else {
22890c7d97c5SJed Brown               aux_ins_indices[i]=j;
22900c7d97c5SJed Brown               j++;
22910c7d97c5SJed Brown             }
22920c7d97c5SJed Brown           }
22930c7d97c5SJed Brown 
2294*da1bb401SStefano Zampini           /*printf("New details localsizes2 localdispl2\n");
2295*da1bb401SStefano Zampini           for(i=0;i<count_recv;i++)
2296*da1bb401SStefano Zampini             printf("(%d %d) ",localsizes2[i],localdispl2[i]);
2297*da1bb401SStefano Zampini           printf("\n");
2298*da1bb401SStefano Zampini           printf("aux_ins_indices 2\n");
2299*da1bb401SStefano Zampini           for(i=0;i<pcbddc->coarse_size;i++)
2300*da1bb401SStefano Zampini             printf("%d ",aux_ins_indices[i]);
2301*da1bb401SStefano Zampini           printf("\n");
2302*da1bb401SStefano Zampini           printf("ins_local_primal_indices\n");
2303*da1bb401SStefano Zampini           for(i=0;i<ins_local_primal_size;i++)
2304*da1bb401SStefano Zampini             printf("%d ",ins_local_primal_indices[i]);
2305*da1bb401SStefano Zampini           printf("\n");
2306*da1bb401SStefano Zampini           printf("coarse_submat_vals\n");
2307*da1bb401SStefano Zampini           for(i=0;i<pcbddc->local_primal_size;i++)
2308*da1bb401SStefano Zampini             for(j=0;j<pcbddc->local_primal_size;j++)
2309*da1bb401SStefano Zampini               printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]);
2310*da1bb401SStefano Zampini           printf("\n");*/
23110c7d97c5SJed Brown 
23120c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
231353cdbc3dSStefano Zampini           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);
23140c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
23150c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
231653cdbc3dSStefano Zampini             ierr = MPI_Isend(&coarse_submat_vals[0],send_size,MPIU_SCALAR,rank_coarse_proc_send_to,666,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
23170c7d97c5SJed Brown           }
231853cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
23190c7d97c5SJed Brown 
2320*da1bb401SStefano Zampini           /*if(coarse_color == 0) {
2321*da1bb401SStefano Zampini             printf("temp_coarse_mat_vals\n");
2322*da1bb401SStefano Zampini             for(k=0;k<count_recv;k++){
2323*da1bb401SStefano Zampini               printf("---- %d ----\n",ranks_recv[k]);
2324*da1bb401SStefano Zampini               for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
2325*da1bb401SStefano Zampini                 for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
2326*da1bb401SStefano Zampini                   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]);
2327*da1bb401SStefano Zampini               printf("\n");
2328*da1bb401SStefano Zampini             }
2329*da1bb401SStefano Zampini           }*/
23300c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
23310c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23320c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
23330c7d97c5SJed Brown 
23340c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
23350c7d97c5SJed Brown           PetscInt row_ind,col_ind;
23360c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
23370c7d97c5SJed Brown             rr = ranks_recv[k];
23380c7d97c5SJed Brown             kk = localdispl2[k];
23390c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
23400c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
2341*da1bb401SStefano Zampini             /*printf("Inserting the following indices (received from %d)\n",rr);*/
23420c7d97c5SJed Brown             for(j=0;j<lps;j++){
23430c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
23440c7d97c5SJed Brown               for(i=0;i<lps;i++){
23450c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
2346*da1bb401SStefano Zampini                 /*printf("%d %d\n",row_ind,col_ind);*/
23470c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
23480c7d97c5SJed Brown               }
23490c7d97c5SJed Brown             }
23500c7d97c5SJed Brown           }
23510c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
23520c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
23530c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
23540c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
23550c7d97c5SJed Brown 
23560c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
23570c7d97c5SJed Brown           {
23580c7d97c5SJed Brown             IS coarse_IS;
235953cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
23600c7d97c5SJed Brown             coarse_comm = prec_comm;
23610c7d97c5SJed Brown             active_rank=rank_prec_comm;
23620c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
23630c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
23640c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
23650c7d97c5SJed Brown           }
23660c7d97c5SJed Brown         }
23670c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
23680c7d97c5SJed Brown           /* arrays for values insertion */
23690c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
23700c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23710c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23720c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23730c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
23740c7d97c5SJed Brown             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];
23750c7d97c5SJed Brown           }
23760c7d97c5SJed Brown         }
23770c7d97c5SJed Brown         break;
23780c7d97c5SJed Brown 
23790c7d97c5SJed Brown     }
23800c7d97c5SJed Brown 
23810c7d97c5SJed Brown     case(GATHERS_BDDC):
23820c7d97c5SJed Brown       {
23830c7d97c5SJed Brown 
23840c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
23850c7d97c5SJed Brown 
23860c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23870c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23880c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
23890c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23900c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
23910c7d97c5SJed Brown           /* arrays for values insertion */
23920c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
23930c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23940c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23950c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
23960c7d97c5SJed Brown           localdispl2[0]=0;
23970c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
23980c7d97c5SJed Brown           j=0;
23990c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
24000c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
24010c7d97c5SJed Brown         }
24020c7d97c5SJed Brown 
24030c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
24040c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
24050c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
240653cdbc3dSStefano Zampini           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);
240753cdbc3dSStefano Zampini           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);
24080c7d97c5SJed Brown         } else {
240953cdbc3dSStefano Zampini           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);
241053cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
24110c7d97c5SJed Brown         }
24120c7d97c5SJed Brown 
24130c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
24140c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
24150c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
24160c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
24170c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
24180c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
24190c7d97c5SJed Brown           }
24200c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
24210c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
24220c7d97c5SJed Brown             offset2=localdispl2[k];
24230c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
24240c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
24250c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
24260c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
24270c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
24280c7d97c5SJed Brown               }
24290c7d97c5SJed Brown             }
24300c7d97c5SJed Brown           }
24310c7d97c5SJed Brown         }
24320c7d97c5SJed Brown         break;
2433*da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
24340c7d97c5SJed Brown   }
24350c7d97c5SJed Brown 
24360c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
24370c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
24380c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
24390c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
24400c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
24410c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
24423b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2443*da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
24443b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24450c7d97c5SJed Brown     } else {
24460c7d97c5SJed Brown       Mat matis_coarse_local_mat;
2447d3ee2243SStefano Zampini       /* remind bs */
2448d3ee2243SStefano Zampini       ierr = MatCreateIS(coarse_comm,bs,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
24493b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24500c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
24513b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2452*da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2453a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24540c7d97c5SJed Brown     }
2455a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
24560c7d97c5SJed Brown     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);
24570c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24580c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24590c7d97c5SJed Brown 
2460*da1bb401SStefano Zampini     /*  PetscViewer view_out;
2461*da1bb401SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"coarsematfull.m",&view_out);CHKERRQ(ierr);
2462*da1bb401SStefano Zampini       ierr = PetscViewerSetFormat(view_out,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2463*da1bb401SStefano Zampini       ierr = MatView(pcbddc->coarse_mat,view_out);CHKERRQ(ierr);
2464*da1bb401SStefano Zampini       ierr = PetscViewerDestroy(&view_out);CHKERRQ(ierr);*/
2465*da1bb401SStefano Zampini 
24660c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
24670c7d97c5SJed Brown     /* Preconditioner for coarse problem */
246853cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
246953cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
247053cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
24713b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
247253cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
247353cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
247453cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
24750c7d97c5SJed Brown     /* Allow user's customization */
2476*da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
247753cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24780c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
247953cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2480e269702eSStefano Zampini       if(dbg_flag) {
2481e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2482e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2483e269702eSStefano Zampini       }
248453cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
248553cdbc3dSStefano Zampini     }
248653cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
24875619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
24885619798eSStefano Zampini       if(dbg_flag) {
24895619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
24905619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24915619798eSStefano Zampini       }
24925619798eSStefano Zampini     }
24930c7d97c5SJed Brown   }
24940c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
24950c7d97c5SJed Brown      IS local_IS,global_IS;
24960c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
24970c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
24980c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
24990c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
25000c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
25010c7d97c5SJed Brown   }
25020c7d97c5SJed Brown 
25030c7d97c5SJed Brown 
25043b03a366Sstefano_zampini   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
25053b03a366Sstefano_zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
25060c7d97c5SJed Brown     PetscScalar m_one=-1.0;
25075619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
25083b03a366Sstefano_zampini     const KSPType check_ksp_type=KSPGMRES;
25090c7d97c5SJed Brown 
25105619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
25113b03a366Sstefano_zampini     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2512d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
25135619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
25145619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2515d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2516d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2517d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2518d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2519d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
25203b03a366Sstefano_zampini     if(dbg_flag) {
25215619798eSStefano Zampini       kappa_2=lambda_max/lambda_min;
25225619798eSStefano Zampini       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2523d49ef151SStefano Zampini       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2524d49ef151SStefano Zampini       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
25253b03a366Sstefano_zampini       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);
2526e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2527e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
25283b03a366Sstefano_zampini     }
25295619798eSStefano Zampini     /* restore coarse ksp to default values */
2530d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
25315619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
25326c9de887SHong Zhang     ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
25333b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
25345619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
25355619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
253653cdbc3dSStefano Zampini   }
25370c7d97c5SJed Brown 
25380c7d97c5SJed Brown   /* free data structures no longer needed */
25390c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
25400c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
25410c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
25420c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
25430c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
25440c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
25450c7d97c5SJed Brown 
25460c7d97c5SJed Brown   PetscFunctionReturn(0);
25470c7d97c5SJed Brown }
25480c7d97c5SJed Brown 
25490c7d97c5SJed Brown #undef __FUNCT__
25500c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
255153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
25520c7d97c5SJed Brown {
25530c7d97c5SJed Brown 
25540c7d97c5SJed Brown   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
25550c7d97c5SJed Brown   PC_IS         *pcis = (PC_IS*)pc->data;
25560c7d97c5SJed Brown   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
2557*da1bb401SStefano Zampini   PCBDDCGraph mat_graph=pcbddc->mat_graph;
2558a0ba757dSStefano Zampini   PetscInt    *queue_in_global_numbering;
25593b03a366Sstefano_zampini   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
2560*da1bb401SStefano Zampini   PetscInt    total_counts,nodes_touched,where_values=1,vertex_size;
25613b03a366Sstefano_zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
2562*da1bb401SStefano Zampini   PetscBool   same_set;
2563a0ba757dSStefano Zampini   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
25643b03a366Sstefano_zampini   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
25653b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
25663b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
256736e030ebSStefano Zampini   IS          used_IS;
2568*da1bb401SStefano Zampini   PetscScalar *array;
2569*da1bb401SStefano Zampini   PetscScalar *array2;
2570*da1bb401SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
25710c7d97c5SJed Brown 
25720c7d97c5SJed Brown   PetscFunctionBegin;
2573*da1bb401SStefano Zampini   /* Setup local adjacency graph */
2574*da1bb401SStefano Zampini   mat_graph->nvtxs=pcis->n;
2575*da1bb401SStefano Zampini   ierr = PCBDDCSetupLocalAdjacencyGraph(pc);CHKERRQ(ierr);
2576a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2577a0ba757dSStefano Zampini   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);
2578a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2579a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2580a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2581a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2582a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25833828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2584a0ba757dSStefano Zampini 
25859c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
25869c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
25879c0446d6SStefano Zampini     PetscInt *is_indices;
25889c0446d6SStefano Zampini     PetscInt is_size;
25899c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
25909c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
25919c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25929c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
25939c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
25949c0446d6SStefano Zampini       }
25959c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25969c0446d6SStefano Zampini     }
25973b03a366Sstefano_zampini     /* use mat block size as vertex size */
25983b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
25993b03a366Sstefano_zampini   } else { /* otherwise it assumes a constant block size */
2600a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
26010c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
26020c7d97c5SJed Brown       for(s=0;s<bs;s++) {
26030c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
26040c7d97c5SJed Brown       }
26050c7d97c5SJed Brown     }
26063b03a366Sstefano_zampini     vertex_size=1;
26079c0446d6SStefano Zampini   }
26083b03a366Sstefano_zampini   /* count number of neigh per node */
26090c7d97c5SJed Brown   total_counts=0;
26103b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26110c7d97c5SJed Brown     s=pcis->n_shared[i];
26120c7d97c5SJed Brown     total_counts+=s;
261353cdbc3dSStefano Zampini     for(j=0;j<s;j++){
26140c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
26150c7d97c5SJed Brown     }
26160c7d97c5SJed Brown   }
26173b03a366Sstefano_zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
261836e030ebSStefano Zampini   ierr = PCBDDCGetNeumannBoundaries(pc,&used_IS);CHKERRQ(ierr);
2619*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
2620*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
262136e030ebSStefano Zampini   if(used_IS) {
262236e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&neumann_bsize);CHKERRQ(ierr);
262336e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
262453cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
262553cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
2626*da1bb401SStefano Zampini       if(mat_graph->count[iindex] > 1 && array[iindex]==0.0){
262753cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26280c7d97c5SJed Brown         total_counts++;
2629*da1bb401SStefano Zampini         array[iindex]=array[iindex]+1.0;
2630*da1bb401SStefano Zampini       } else if(array[iindex]>0.0) {
2631*da1bb401SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Error for neumann nodes provided to BDDC! They must be uniquely listed! Found duplicate node %d\n",iindex);
26320c7d97c5SJed Brown       }
26330c7d97c5SJed Brown     }
26340c7d97c5SJed Brown   }
2635*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2636*da1bb401SStefano Zampini   /* allocate space for storing the set of neighbours for each node */
2637*da1bb401SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&mat_graph->neighbours_set);CHKERRQ(ierr);
2638*da1bb401SStefano Zampini   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&mat_graph->neighbours_set[0]);CHKERRQ(ierr); }
2639*da1bb401SStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) mat_graph->neighbours_set[i]=mat_graph->neighbours_set[i-1]+mat_graph->count[i-1];
2640a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
26413b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26420c7d97c5SJed Brown     s=pcis->n_shared[i];
26430c7d97c5SJed Brown     for(j=0;j<s;j++) {
26440c7d97c5SJed Brown       k=pcis->shared[i][j];
2645*da1bb401SStefano Zampini       mat_graph->neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
26460c7d97c5SJed Brown       mat_graph->count[k]+=1;
26470c7d97c5SJed Brown     }
26480c7d97c5SJed Brown   }
2649*da1bb401SStefano Zampini   /* Check consistency of Neumann nodes */
2650*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2651*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2652*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2653*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2654*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2655*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
26563b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
265736e030ebSStefano Zampini   if(used_IS) {
265853cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
265953cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
26603b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
2661*da1bb401SStefano Zampini         if(mat_graph->count[iindex]+1 != (PetscInt)array[iindex]) {
2662*da1bb401SStefano Zampini           SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Neumann nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,mat_graph->count[iindex]+1,(PetscInt)array[iindex]);
2663*da1bb401SStefano Zampini         }
2664*da1bb401SStefano Zampini         mat_graph->neighbours_set[iindex][mat_graph->count[iindex]] = -1;
266553cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26660c7d97c5SJed Brown       }
26670c7d97c5SJed Brown     }
266836e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
26690c7d97c5SJed Brown   }
2670*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2671*da1bb401SStefano Zampini   /* sort set of sharing subdomains */
2672*da1bb401SStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],mat_graph->neighbours_set[i]);CHKERRQ(ierr); }
26733b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
2674*da1bb401SStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2675*da1bb401SStefano Zampini   nodes_touched=0;
267636e030ebSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&used_IS);CHKERRQ(ierr);
2677*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec2_N,0.0);CHKERRQ(ierr);
2678*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2679*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2680*da1bb401SStefano Zampini   if(used_IS) {
2681*da1bb401SStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
2682*da1bb401SStefano Zampini     if(dirichlet_bsize && matis->pure_neumann) {
2683*da1bb401SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet boundaries are intended to be used with matrices with zeroed rows!\n");
2684*da1bb401SStefano Zampini     }
2685*da1bb401SStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
2686*da1bb401SStefano Zampini     for(i=0;i<dirichlet_bsize;i++){
2687*da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
2688*da1bb401SStefano Zampini       if(mat_graph->count[iindex] && !mat_graph->touched[iindex]) {
2689*da1bb401SStefano Zampini         if(array[iindex]>0.0) {
2690*da1bb401SStefano Zampini           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"BDDC cannot have nodes which are marked as Neumann and Dirichlet at the same time! Wrong node %d\n",iindex);
2691*da1bb401SStefano Zampini         }
2692*da1bb401SStefano Zampini         mat_graph->touched[iindex]=PETSC_TRUE;
2693*da1bb401SStefano Zampini         mat_graph->where[iindex]=0;
2694*da1bb401SStefano Zampini         nodes_touched++;
2695*da1bb401SStefano Zampini         array2[iindex]=array2[iindex]+1.0;
2696*da1bb401SStefano Zampini       }
2697*da1bb401SStefano Zampini     }
2698*da1bb401SStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
2699*da1bb401SStefano Zampini   }
2700*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2701*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2702*da1bb401SStefano Zampini   /* Check consistency of Dirichlet nodes */
2703*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
2704*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2705*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2706*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2707*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2708*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2709*da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2710*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2711*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2712*da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2713*da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2714*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2715*da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
271636e030ebSStefano Zampini   if(used_IS) {
271736e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
271836e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
27193b03a366Sstefano_zampini     for(i=0;i<dirichlet_bsize;i++){
2720*da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
2721*da1bb401SStefano Zampini       if(array[iindex]>1.0 && array[iindex]!=array2[iindex] ) {
2722*da1bb401SStefano Zampini          SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,(PetscInt)array[iindex],(PetscInt)array2[iindex]);
2723*da1bb401SStefano Zampini       }
27243b03a366Sstefano_zampini     }
272536e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
27263b03a366Sstefano_zampini   }
2727*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2728*da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2729*da1bb401SStefano Zampini 
27300c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
27313b03a366Sstefano_zampini     if(!mat_graph->count[i]){  /* interior nodes */
27320c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
27330c7d97c5SJed Brown       mat_graph->where[i]=0;
27340c7d97c5SJed Brown       nodes_touched++;
27350c7d97c5SJed Brown     }
27360c7d97c5SJed Brown   }
27370c7d97c5SJed Brown   mat_graph->ncmps = 0;
2738*da1bb401SStefano Zampini   i=0;
27390c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2740a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
27410c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
27420c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2743a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
27440c7d97c5SJed Brown     nodes_touched++;
2745a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
27460c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2747a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
2748*da1bb401SStefano Zampini       if(!mat_graph->touched[j] && mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2749a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
27500c7d97c5SJed Brown         same_set=PETSC_TRUE;
27510c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
2752*da1bb401SStefano Zampini           if(mat_graph->neighbours_set[i][k]!=mat_graph->neighbours_set[j][k]) {
27530c7d97c5SJed Brown             same_set=PETSC_FALSE;
27540c7d97c5SJed Brown           }
27550c7d97c5SJed Brown         }
2756a0ba757dSStefano Zampini         /* I found a friend of mine */
27570c7d97c5SJed Brown         if(same_set) {
2758a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
27590c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
27600c7d97c5SJed Brown           nodes_touched++;
27610c7d97c5SJed Brown         }
27620c7d97c5SJed Brown       }
27630c7d97c5SJed Brown     }
2764a0ba757dSStefano Zampini     where_values++;
27650c7d97c5SJed Brown   }
2766a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2767a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2768a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2769a0ba757dSStefano Zampini   if(where_values) {
2770a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
27713b03a366Sstefano_zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2772a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2773a0ba757dSStefano Zampini       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);
2774a0ba757dSStefano Zampini       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);
2775a0ba757dSStefano Zampini     }
2776a0ba757dSStefano Zampini   }
2777a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2778a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
27793b03a366Sstefano_zampini     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
27803b03a366Sstefano_zampini     if(mat_graph->where_ncmps[i]>1) {
2781a0ba757dSStefano Zampini       adapt_interface=1;
2782a0ba757dSStefano Zampini       break;
2783a0ba757dSStefano Zampini     }
2784a0ba757dSStefano Zampini   }
2785a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2786*da1bb401SStefano Zampini   if(pcbddc->dbg_flag && adapt_interface_reduced) {
2787*da1bb401SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Interface adapted\n");CHKERRQ(ierr);
2788*da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2789*da1bb401SStefano Zampini   }
2790a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
27910c7d97c5SJed Brown 
27923b03a366Sstefano_zampini 
2793a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2794a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2795a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2796a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2797a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2798a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2799a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2800a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2801a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2802a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2803a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2804a0ba757dSStefano Zampini     MPI_Request *send_requests;
2805a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2806a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2807a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2808a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2809a0ba757dSStefano Zampini     PetscInt *add_to_where;
2810a0ba757dSStefano Zampini 
2811a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2812a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2813a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2814a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2815a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2816a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2817a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2818a0ba757dSStefano Zampini       j=0;
2819a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2820a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
2821*da1bb401SStefano Zampini       if(mat_graph->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  */
28223b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2823a0ba757dSStefano Zampini     }
2824a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2825a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2826a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2827a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2828a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2829a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2830a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2831a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2832a0ba757dSStefano Zampini     }
2833a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2834a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2835a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2836*da1bb401SStefano Zampini       k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2837a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2838*da1bb401SStefano Zampini         ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2839*da1bb401SStefano Zampini         ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2840a0ba757dSStefano Zampini         sum_requests++;
2841a0ba757dSStefano Zampini       }
2842a0ba757dSStefano Zampini     }
2843a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2844a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2845a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2846a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2847a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2848a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2849a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
28503b03a366Sstefano_zampini         /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
28513b03a366Sstefano_zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2852a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2853a0ba757dSStefano Zampini           break;
2854a0ba757dSStefano Zampini         }
2855a0ba757dSStefano Zampini       }
2856a0ba757dSStefano Zampini     }
2857a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2858a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2859a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2860a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2861a0ba757dSStefano Zampini     sum_requests=0;
2862a0ba757dSStefano Zampini     start_of_send=0;
2863a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2864a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2865a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2866a0ba757dSStefano Zampini         size_of_send=0;
2867a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2868a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2869a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2870a0ba757dSStefano Zampini             size_of_send+=1;
2871a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2872a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2873a0ba757dSStefano Zampini             }
2874a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2875a0ba757dSStefano Zampini           }
2876a0ba757dSStefano Zampini         }
2877a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2878*da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2879a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2880*da1bb401SStefano Zampini           ierr = MPI_Isend(&size_of_send,1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2881*da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2882a0ba757dSStefano Zampini           sum_requests++;
2883a0ba757dSStefano Zampini         }
2884a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2885a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2886a0ba757dSStefano Zampini       }
2887a0ba757dSStefano Zampini     }
2888a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2889a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2890a0ba757dSStefano Zampini     buffer_size=0;
2891a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2892a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2893a0ba757dSStefano Zampini     /* now exchange the data */
2894a0ba757dSStefano Zampini     start_of_recv=0;
2895a0ba757dSStefano Zampini     start_of_send=0;
2896a0ba757dSStefano Zampini     sum_requests=0;
2897a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2898a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2899a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2900a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2901*da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2902a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2903*da1bb401SStefano Zampini           ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2904a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2905*da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2906a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2907a0ba757dSStefano Zampini           sum_requests++;
2908a0ba757dSStefano Zampini         }
2909a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2910a0ba757dSStefano Zampini       }
2911a0ba757dSStefano Zampini     }
2912a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2913a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2914a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2915a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2916a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2917a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2918a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2919a0ba757dSStefano Zampini        j+=k;
2920a0ba757dSStefano Zampini     }
2921a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2922a0ba757dSStefano Zampini     start_of_recv=0;
2923a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2924a0ba757dSStefano Zampini     global_where_counter=0;
2925a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2926a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2927a0ba757dSStefano Zampini         temp_buffer_size=0;
2928a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2929a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2930a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2931a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2932a0ba757dSStefano Zampini             temp_buffer_size++;
2933a0ba757dSStefano Zampini           } else {
2934a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2935a0ba757dSStefano Zampini           }
2936a0ba757dSStefano Zampini         }
2937a0ba757dSStefano Zampini         /* allocate some temporary space */
2938a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2939a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2940a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2941a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2942a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2943a0ba757dSStefano Zampini         }
2944a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2945a0ba757dSStefano Zampini            temp buffer structure:
2946a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2947a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2948a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2949a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2950a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2951a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2952a0ba757dSStefano Zampini              [ 0, 0, 0;
2953a0ba757dSStefano Zampini                0, 0, 1;
2954a0ba757dSStefano Zampini                1, 1, 2;
2955a0ba757dSStefano Zampini                1, 1, 2;
2956a0ba757dSStefano Zampini                0, 1, 0; ];
2957a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2958a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2959a0ba757dSStefano Zampini                                                                                                                                    */
2960a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2961a0ba757dSStefano Zampini           ins_val=0;
2962a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2963a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2964a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2965a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2966a0ba757dSStefano Zampini             }
2967a0ba757dSStefano Zampini             buffer_size+=k;
2968a0ba757dSStefano Zampini             ins_val++;
2969a0ba757dSStefano Zampini           }
2970a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2971a0ba757dSStefano Zampini           sum_requests++;
2972a0ba757dSStefano Zampini         }
2973a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2974a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2975a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2976a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2977a0ba757dSStefano Zampini             global_where_counter++;
2978a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2979a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2980a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2981a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2982a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2983a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2984a0ba757dSStefano Zampini                   break;
2985a0ba757dSStefano Zampini                 }
2986a0ba757dSStefano Zampini               }
2987a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2988a0ba757dSStefano Zampini             }
2989a0ba757dSStefano Zampini           }
2990a0ba757dSStefano Zampini         }
2991a0ba757dSStefano Zampini         /* insert new data in where array */
2992a0ba757dSStefano Zampini         temp_buffer_size=0;
2993a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2994a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2995a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2996a0ba757dSStefano Zampini             temp_buffer_size++;
2997a0ba757dSStefano Zampini           }
2998a0ba757dSStefano Zampini         }
2999a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
3000a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
3001a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
3002a0ba757dSStefano Zampini       }
3003a0ba757dSStefano Zampini     }
3004a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
3005a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
3006a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
3007a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
3008a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
3009a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
3010a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
3011a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
3012a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
3013a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
3014a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
3015a0ba757dSStefano Zampini     if(global_where_counter) {
3016a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
3017a0ba757dSStefano Zampini       global_where_counter=0;
3018a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
3019a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
3020a0ba757dSStefano Zampini           global_where_counter++;
3021a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
3022a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
3023a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
3024a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
3025a0ba757dSStefano Zampini             }
3026a0ba757dSStefano Zampini           }
3027a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
3028a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
3029a0ba757dSStefano Zampini         }
3030a0ba757dSStefano Zampini       }
3031a0ba757dSStefano Zampini       where_values=global_where_counter;
3032a0ba757dSStefano Zampini     }
3033a0ba757dSStefano Zampini     if(global_where_counter) {
3034a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
3035a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
3036a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
3037a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
3038a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
3039a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
3040a0ba757dSStefano Zampini         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);
3041a0ba757dSStefano Zampini         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);
3042a0ba757dSStefano Zampini       }
3043a0ba757dSStefano Zampini     }
30443b03a366Sstefano_zampini   } /* Finished adapting interface */
30450c7d97c5SJed Brown   PetscInt nfc=0;
30460c7d97c5SJed Brown   PetscInt nec=0;
30470c7d97c5SJed Brown   PetscInt nvc=0;
30483b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
30490c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
30503b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
30513b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
30520c7d97c5SJed Brown         nfc++;
30533b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
30543b03a366Sstefano_zampini         nec++;
30553b03a366Sstefano_zampini       }
30560c7d97c5SJed Brown     } else {
30573b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
30583b03a366Sstefano_zampini     }
30593b03a366Sstefano_zampini   }
30603b03a366Sstefano_zampini 
30613b03a366Sstefano_zampini   if(!nec) { /* we are in a 2d case -> no faces, only edges */
30623b03a366Sstefano_zampini     nec = nfc;
30633b03a366Sstefano_zampini     nfc = 0;
30643b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
30653b03a366Sstefano_zampini   }
30663b03a366Sstefano_zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set.
30673b03a366Sstefano_zampini      Reusing space allocated in mat_graph->where for creating IS objects */
30683b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
30693b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
30703b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
30713b03a366Sstefano_zampini   }
30723b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
30733b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
30743b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
30753b03a366Sstefano_zampini   }
30763b03a366Sstefano_zampini   nfc=0;
30773b03a366Sstefano_zampini   nec=0;
30783b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
30793b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
30803b03a366Sstefano_zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
30813b03a366Sstefano_zampini         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
30823b03a366Sstefano_zampini       }
30833b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
30843b03a366Sstefano_zampini         if(twodim_flag) {
30853b03a366Sstefano_zampini           if(use_edges) {
30863b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30873b03a366Sstefano_zampini             nec++;
30883b03a366Sstefano_zampini           }
30893b03a366Sstefano_zampini         } else {
30903b03a366Sstefano_zampini           if(use_faces) {
30913b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
30923b03a366Sstefano_zampini             nfc++;
30933b03a366Sstefano_zampini           }
30943b03a366Sstefano_zampini         }
30953b03a366Sstefano_zampini       } else {
30963b03a366Sstefano_zampini         if(use_edges) {
30973b03a366Sstefano_zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30980c7d97c5SJed Brown           nec++;
30990c7d97c5SJed Brown         }
31000c7d97c5SJed Brown       }
31010c7d97c5SJed Brown     }
31023b03a366Sstefano_zampini   }
31033b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
31043b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
31053b03a366Sstefano_zampini   nvc=0;
31060c7d97c5SJed Brown   if( !pcbddc->constraints_flag ) {
31073b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
31083b03a366Sstefano_zampini       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
31093b03a366Sstefano_zampini         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
31103b03a366Sstefano_zampini           mat_graph->where[nvc]=mat_graph->queue[j];
31110c7d97c5SJed Brown           nvc++;
31120c7d97c5SJed Brown         }
31130c7d97c5SJed Brown       }
31140c7d97c5SJed Brown     }
31150c7d97c5SJed Brown   }
3116a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
31173b03a366Sstefano_zampini   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
31183b03a366Sstefano_zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
31190c7d97c5SJed Brown 
3120e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
3121e269702eSStefano Zampini 
3122d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3123d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3124d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3125a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
3126a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3127e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
3128a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);CHKERRQ(ierr);
3129e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
3130a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
3131e269702eSStefano Zampini       }
3132a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
3133*da1bb401SStefano Zampini     }*/
3134d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
31350c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
31363b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
31373b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
3138*da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"subdomains: ");
3139*da1bb401SStefano Zampini       for (j=0;j<mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]; j++) {
3140*da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->neighbours_set[mat_graph->queue[mat_graph->cptr[i]]][j]);
3141*da1bb401SStefano Zampini       }
3142*da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");
31430c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
3144*da1bb401SStefano Zampini         /* ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr); */
3145*da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d, ",mat_graph->queue[j]);CHKERRQ(ierr);
31460c7d97c5SJed Brown       }
31470c7d97c5SJed Brown     }
3148*da1bb401SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
31493b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
31503b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
31513b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3152d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31530c7d97c5SJed Brown   }
31540c7d97c5SJed Brown 
3155a0ba757dSStefano Zampini   /* Free graph structure */
31560c7d97c5SJed Brown   if(mat_graph->nvtxs){
3157a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3158a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3159a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
31600c7d97c5SJed Brown   }
31610c7d97c5SJed Brown 
31620c7d97c5SJed Brown   PetscFunctionReturn(0);
31630c7d97c5SJed Brown 
31640c7d97c5SJed Brown }
31650c7d97c5SJed Brown 
31660c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
31670c7d97c5SJed Brown 
31680c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
3169*da1bb401SStefano Zampini    in source file contig.c of METIS library (version 5.0.1)
3170*da1bb401SStefano Zampini    It finds connected components of each partition labeled from 1 to n_dist  */
31710c7d97c5SJed Brown 
31720c7d97c5SJed Brown #undef __FUNCT__
31730c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
31749c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
31750c7d97c5SJed Brown {
31760c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
31770c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
31780c7d97c5SJed Brown   PetscInt *cptr;
31790c7d97c5SJed Brown   PetscBool *touched;
31800c7d97c5SJed Brown 
31810c7d97c5SJed Brown   PetscFunctionBegin;
31820c7d97c5SJed Brown 
31830c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
31840c7d97c5SJed Brown   xadj    = graph->xadj;
31850c7d97c5SJed Brown   adjncy  = graph->adjncy;
31860c7d97c5SJed Brown   where   = graph->where;
31870c7d97c5SJed Brown   touched = graph->touched;
31880c7d97c5SJed Brown   queue   = graph->queue;
31890c7d97c5SJed Brown   cptr    = graph->cptr;
31900c7d97c5SJed Brown 
31910c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
31920c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
31930c7d97c5SJed Brown 
31940c7d97c5SJed Brown   cum_queue=0;
31950c7d97c5SJed Brown   ncmps=0;
31960c7d97c5SJed Brown 
31970c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
3198*da1bb401SStefano Zampini     pid = n+1;  /* partition labeled by 0 is discarded */
31990c7d97c5SJed Brown     nleft = 0;
32000c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
32010c7d97c5SJed Brown       if (where[i] == pid)
32020c7d97c5SJed Brown         nleft++;
32030c7d97c5SJed Brown     }
32040c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
32050c7d97c5SJed Brown       if (where[i] == pid)
32060c7d97c5SJed Brown         break;
32070c7d97c5SJed Brown     }
32080c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
32090c7d97c5SJed Brown     queue[cum_queue] = i;
32100c7d97c5SJed Brown     first = 0; last = 1;
32110c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
32120c7d97c5SJed Brown     ncmps_pid = 0;
32130c7d97c5SJed Brown     while (first != nleft) {
32140c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
32150c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
32160c7d97c5SJed Brown         ncmps_pid++;
32170c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
32180c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
32190c7d97c5SJed Brown             break;
32200c7d97c5SJed Brown         }
32210c7d97c5SJed Brown         queue[cum_queue+last] = i;
32220c7d97c5SJed Brown         last++;
32230c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
32240c7d97c5SJed Brown       }
32250c7d97c5SJed Brown       i = queue[cum_queue+first];
32260c7d97c5SJed Brown       first++;
32270c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
32280c7d97c5SJed Brown         k = adjncy[j];
32290c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
32300c7d97c5SJed Brown           queue[cum_queue+last] = k;
32310c7d97c5SJed Brown           last++;
32320c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
32330c7d97c5SJed Brown         }
32340c7d97c5SJed Brown       }
32350c7d97c5SJed Brown     }
32360c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
32370c7d97c5SJed Brown     ncmps_pid++;
32380c7d97c5SJed Brown     cum_queue=cptr[ncmps];
3239a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
32400c7d97c5SJed Brown   }
32410c7d97c5SJed Brown   graph->ncmps = ncmps;
32420c7d97c5SJed Brown 
32430c7d97c5SJed Brown   PetscFunctionReturn(0);
32440c7d97c5SJed Brown }
32450c7d97c5SJed Brown 
3246