xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 8ce42a968a7c9c62a1a503b5a381eaf1d8dbcaa1)
153cdbc3dSStefano Zampini /* TODOLIST
2da1bb401SStefano Zampini    DofSplitting and DM attached to pc?
3da1bb401SStefano Zampini    Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
4a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
5a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
6a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
7674ae819SStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in PCBDDCAnalyzeInterface?
8a0ba757dSStefano Zampini    code refactoring:
9a0ba757dSStefano Zampini      - pick up better names for static functions
10a0ba757dSStefano Zampini    change options structure:
11a0ba757dSStefano Zampini      - insert BDDC into MG framework?
12a0ba757dSStefano Zampini    provide other ops? Ask to developers
13a0ba757dSStefano Zampini    remove all unused printf
14a0ba757dSStefano Zampini    man pages
1553cdbc3dSStefano Zampini */
160c7d97c5SJed Brown 
1753cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
180c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
190c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2053cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2153cdbc3dSStefano Zampini 
22674ae819SStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23674ae819SStefano Zampini #include "bddcprivate.h"
243b03a366Sstefano_zampini #include <petscblaslapack.h>
25674ae819SStefano Zampini 
26674ae819SStefano Zampini /* prototypes for static functions contained in bddc.c */
27674ae819SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC,PetscInt);
28674ae819SStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC);
29674ae819SStefano Zampini 
300c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
310c7d97c5SJed Brown #undef __FUNCT__
320c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
330c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
340c7d97c5SJed Brown {
350c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
360c7d97c5SJed Brown   PetscErrorCode ierr;
370c7d97c5SJed Brown 
380c7d97c5SJed Brown   PetscFunctionBegin;
390c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
400c7d97c5SJed Brown   /* Verbose debugging of main data structures */
419d9e44b6SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,NULL);CHKERRQ(ierr);
420c7d97c5SJed Brown   /* Some customization for default primal space */
430298fd71SBarry Smith   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use only vertices in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,NULL);CHKERRQ(ierr);
440298fd71SBarry Smith   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use only constraints in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,NULL);CHKERRQ(ierr);
450298fd71SBarry Smith   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      ,NULL);CHKERRQ(ierr);
460298fd71SBarry Smith   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      ,NULL);CHKERRQ(ierr);
470c7d97c5SJed Brown   /* Coarse solver context */
486c667b0aSStefano Zampini   static const char * const avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel","CoarseProblemType","PC_BDDC_",0}; /*order of choiches depends on ENUM defined in bddc.h */
490298fd71SBarry Smith   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,NULL);CHKERRQ(ierr);
500c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
510298fd71SBarry Smith   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->inexact_prec_type,&pcbddc->inexact_prec_type,NULL);CHKERRQ(ierr);
52674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use change of basis approach for primal space","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr);
53674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use change of basis approach for face constraints","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr);
54674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
55674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
56674ae819SStefano Zampini   }
570298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
580298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
59674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
600c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
610c7d97c5SJed Brown   PetscFunctionReturn(0);
620c7d97c5SJed Brown }
630c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
64674ae819SStefano Zampini #undef __FUNCT__
65674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
66674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
67674ae819SStefano Zampini {
68674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
69674ae819SStefano Zampini   PetscErrorCode ierr;
701e6b0712SBarry Smith 
71674ae819SStefano Zampini   PetscFunctionBegin;
72674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
73674ae819SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
74674ae819SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
75674ae819SStefano Zampini   PetscFunctionReturn(0);
76674ae819SStefano Zampini }
77674ae819SStefano Zampini #undef __FUNCT__
78674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
79674ae819SStefano Zampini /*@
80674ae819SStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC.
81674ae819SStefano Zampini 
82674ae819SStefano Zampini    Not collective
83674ae819SStefano Zampini 
84674ae819SStefano Zampini    Input Parameters:
85674ae819SStefano Zampini +  pc - the preconditioning context
86674ae819SStefano Zampini -  PrimalVertices - index sets of primal vertices in local numbering
87674ae819SStefano Zampini 
88674ae819SStefano Zampini    Level: intermediate
89674ae819SStefano Zampini 
90674ae819SStefano Zampini    Notes:
91674ae819SStefano Zampini 
92674ae819SStefano Zampini .seealso: PCBDDC
93674ae819SStefano Zampini @*/
94674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
95674ae819SStefano Zampini {
96674ae819SStefano Zampini   PetscErrorCode ierr;
97674ae819SStefano Zampini 
98674ae819SStefano Zampini   PetscFunctionBegin;
99674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
100674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
101674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
102674ae819SStefano Zampini   PetscFunctionReturn(0);
103674ae819SStefano Zampini }
104674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
1050c7d97c5SJed Brown #undef __FUNCT__
1060c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
10753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
1080c7d97c5SJed Brown {
1090c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1100c7d97c5SJed Brown 
1110c7d97c5SJed Brown   PetscFunctionBegin;
1120c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
1130c7d97c5SJed Brown   PetscFunctionReturn(0);
1140c7d97c5SJed Brown }
1151e6b0712SBarry Smith 
1160c7d97c5SJed Brown #undef __FUNCT__
1170c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
11853cdbc3dSStefano Zampini /*@
1199c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
12053cdbc3dSStefano Zampini 
1219c0446d6SStefano Zampini    Not collective
12253cdbc3dSStefano Zampini 
12353cdbc3dSStefano Zampini    Input Parameters:
12453cdbc3dSStefano Zampini +  pc - the preconditioning context
12553cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
12653cdbc3dSStefano Zampini 
12753cdbc3dSStefano Zampini    Level: intermediate
12853cdbc3dSStefano Zampini 
12953cdbc3dSStefano Zampini    Notes:
130da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
13153cdbc3dSStefano Zampini 
13253cdbc3dSStefano Zampini .seealso: PCBDDC
13353cdbc3dSStefano Zampini @*/
1340c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
1350c7d97c5SJed Brown {
1360c7d97c5SJed Brown   PetscErrorCode ierr;
1370c7d97c5SJed Brown 
1380c7d97c5SJed Brown   PetscFunctionBegin;
1390c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1400c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
1410c7d97c5SJed Brown   PetscFunctionReturn(0);
1420c7d97c5SJed Brown }
1430c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1440c7d97c5SJed Brown #undef __FUNCT__
1454fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
1464fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
1474fad6a16SStefano Zampini {
1484fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1494fad6a16SStefano Zampini 
1504fad6a16SStefano Zampini   PetscFunctionBegin;
1514fad6a16SStefano Zampini   pcbddc->coarsening_ratio=k;
1524fad6a16SStefano Zampini   PetscFunctionReturn(0);
1534fad6a16SStefano Zampini }
1541e6b0712SBarry Smith 
1554fad6a16SStefano Zampini #undef __FUNCT__
1564fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
1574fad6a16SStefano Zampini /*@
1584fad6a16SStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
1594fad6a16SStefano Zampini 
1604fad6a16SStefano Zampini    Logically collective on PC
1614fad6a16SStefano Zampini 
1624fad6a16SStefano Zampini    Input Parameters:
1634fad6a16SStefano Zampini +  pc - the preconditioning context
1644fad6a16SStefano Zampini -  k - coarsening ratio
1654fad6a16SStefano Zampini 
1664fad6a16SStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
1674fad6a16SStefano Zampini 
1684fad6a16SStefano Zampini    Level: intermediate
1694fad6a16SStefano Zampini 
1704fad6a16SStefano Zampini    Notes:
1714fad6a16SStefano Zampini 
1724fad6a16SStefano Zampini .seealso: PCBDDC
1734fad6a16SStefano Zampini @*/
1744fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
1754fad6a16SStefano Zampini {
1764fad6a16SStefano Zampini   PetscErrorCode ierr;
1774fad6a16SStefano Zampini 
1784fad6a16SStefano Zampini   PetscFunctionBegin;
1794fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1804fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
1814fad6a16SStefano Zampini   PetscFunctionReturn(0);
1824fad6a16SStefano Zampini }
1834fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1841e6b0712SBarry Smith 
1854fad6a16SStefano Zampini #undef __FUNCT__
1864fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
1874fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
1884fad6a16SStefano Zampini {
1894fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1904fad6a16SStefano Zampini 
1914fad6a16SStefano Zampini   PetscFunctionBegin;
1924fad6a16SStefano Zampini   pcbddc->max_levels=max_levels;
1934fad6a16SStefano Zampini   PetscFunctionReturn(0);
1944fad6a16SStefano Zampini }
1951e6b0712SBarry Smith 
1964fad6a16SStefano Zampini #undef __FUNCT__
1974fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels"
1984fad6a16SStefano Zampini /*@
1994fad6a16SStefano Zampini  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
2004fad6a16SStefano Zampini 
2014fad6a16SStefano Zampini    Logically collective on PC
2024fad6a16SStefano Zampini 
2034fad6a16SStefano Zampini    Input Parameters:
2044fad6a16SStefano Zampini +  pc - the preconditioning context
2054fad6a16SStefano Zampini -  max_levels - the maximum number of levels
2064fad6a16SStefano Zampini 
2074fad6a16SStefano Zampini    Default value is 1, i.e. coarse problem will be solved inexactly with one application
2084fad6a16SStefano Zampini    of PCBDDC preconditioner if the multilevel approach is requested.
2094fad6a16SStefano Zampini 
2104fad6a16SStefano Zampini    Level: intermediate
2114fad6a16SStefano Zampini 
2124fad6a16SStefano Zampini    Notes:
2134fad6a16SStefano Zampini 
2144fad6a16SStefano Zampini .seealso: PCBDDC
2154fad6a16SStefano Zampini @*/
2164fad6a16SStefano Zampini PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
2174fad6a16SStefano Zampini {
2184fad6a16SStefano Zampini   PetscErrorCode ierr;
2194fad6a16SStefano Zampini 
2204fad6a16SStefano Zampini   PetscFunctionBegin;
2214fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2224fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
2234fad6a16SStefano Zampini   PetscFunctionReturn(0);
2244fad6a16SStefano Zampini }
2254fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
2261e6b0712SBarry Smith 
2274fad6a16SStefano Zampini #undef __FUNCT__
2280bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
2290bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
2300bdf917eSStefano Zampini {
2310bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2320bdf917eSStefano Zampini   PetscErrorCode ierr;
2330bdf917eSStefano Zampini 
2340bdf917eSStefano Zampini   PetscFunctionBegin;
2350bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
2360bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
2370bdf917eSStefano Zampini   pcbddc->NullSpace=NullSpace;
2380bdf917eSStefano Zampini   PetscFunctionReturn(0);
2390bdf917eSStefano Zampini }
2401e6b0712SBarry Smith 
2410bdf917eSStefano Zampini #undef __FUNCT__
2420bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
2430bdf917eSStefano Zampini /*@
2440bdf917eSStefano Zampini  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
2450bdf917eSStefano Zampini 
2460bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
2470bdf917eSStefano Zampini 
2480bdf917eSStefano Zampini    Input Parameters:
2490bdf917eSStefano Zampini +  pc - the preconditioning context
2500bdf917eSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned.
2510bdf917eSStefano Zampini 
2520bdf917eSStefano Zampini    Level: intermediate
2530bdf917eSStefano Zampini 
2540bdf917eSStefano Zampini    Notes:
2550bdf917eSStefano Zampini 
2560bdf917eSStefano Zampini .seealso: PCBDDC
2570bdf917eSStefano Zampini @*/
2580bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
2590bdf917eSStefano Zampini {
2600bdf917eSStefano Zampini   PetscErrorCode ierr;
2610bdf917eSStefano Zampini 
2620bdf917eSStefano Zampini   PetscFunctionBegin;
2630bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
264674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
2650bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
2660bdf917eSStefano Zampini   PetscFunctionReturn(0);
2670bdf917eSStefano Zampini }
2680bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
2691e6b0712SBarry Smith 
2700bdf917eSStefano Zampini #undef __FUNCT__
2713b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
2723b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
2733b03a366Sstefano_zampini {
2743b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2753b03a366Sstefano_zampini   PetscErrorCode ierr;
2763b03a366Sstefano_zampini 
2773b03a366Sstefano_zampini   PetscFunctionBegin;
2783b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
27936e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
28036e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
2813b03a366Sstefano_zampini   PetscFunctionReturn(0);
2823b03a366Sstefano_zampini }
2831e6b0712SBarry Smith 
2843b03a366Sstefano_zampini #undef __FUNCT__
2853b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
2863b03a366Sstefano_zampini /*@
287da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
288da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
2893b03a366Sstefano_zampini 
2903b03a366Sstefano_zampini    Not collective
2913b03a366Sstefano_zampini 
2923b03a366Sstefano_zampini    Input Parameters:
2933b03a366Sstefano_zampini +  pc - the preconditioning context
2940298fd71SBarry Smith -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL)
2953b03a366Sstefano_zampini 
2963b03a366Sstefano_zampini    Level: intermediate
2973b03a366Sstefano_zampini 
2983b03a366Sstefano_zampini    Notes:
2993b03a366Sstefano_zampini 
3003b03a366Sstefano_zampini .seealso: PCBDDC
3013b03a366Sstefano_zampini @*/
3023b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
3033b03a366Sstefano_zampini {
3043b03a366Sstefano_zampini   PetscErrorCode ierr;
3053b03a366Sstefano_zampini 
3063b03a366Sstefano_zampini   PetscFunctionBegin;
3073b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
308674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
3093b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
3103b03a366Sstefano_zampini   PetscFunctionReturn(0);
3113b03a366Sstefano_zampini }
3123b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
3131e6b0712SBarry Smith 
3143b03a366Sstefano_zampini #undef __FUNCT__
3150c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
31653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
3170c7d97c5SJed Brown {
3180c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
31953cdbc3dSStefano Zampini   PetscErrorCode ierr;
3200c7d97c5SJed Brown 
3210c7d97c5SJed Brown   PetscFunctionBegin;
32253cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
32336e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
32436e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
3250c7d97c5SJed Brown   PetscFunctionReturn(0);
3260c7d97c5SJed Brown }
3271e6b0712SBarry Smith 
3280c7d97c5SJed Brown #undef __FUNCT__
3290c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
33057527edcSJed Brown /*@
331da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
332da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
33357527edcSJed Brown 
3349c0446d6SStefano Zampini    Not collective
33557527edcSJed Brown 
33657527edcSJed Brown    Input Parameters:
33757527edcSJed Brown +  pc - the preconditioning context
3380298fd71SBarry Smith -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL)
33957527edcSJed Brown 
34057527edcSJed Brown    Level: intermediate
34157527edcSJed Brown 
34257527edcSJed Brown    Notes:
34357527edcSJed Brown 
34457527edcSJed Brown .seealso: PCBDDC
34557527edcSJed Brown @*/
34653cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
3470c7d97c5SJed Brown {
3480c7d97c5SJed Brown   PetscErrorCode ierr;
3490c7d97c5SJed Brown 
3500c7d97c5SJed Brown   PetscFunctionBegin;
3510c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
352674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
35353cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
35453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
35553cdbc3dSStefano Zampini }
35653cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
3571e6b0712SBarry Smith 
35853cdbc3dSStefano Zampini #undef __FUNCT__
359da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
360da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
361da1bb401SStefano Zampini {
362da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
363da1bb401SStefano Zampini 
364da1bb401SStefano Zampini   PetscFunctionBegin;
365da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
366da1bb401SStefano Zampini   PetscFunctionReturn(0);
367da1bb401SStefano Zampini }
3681e6b0712SBarry Smith 
369da1bb401SStefano Zampini #undef __FUNCT__
370da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
371da1bb401SStefano Zampini /*@
372da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
373da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
374da1bb401SStefano Zampini 
375da1bb401SStefano Zampini    Not collective
376da1bb401SStefano Zampini 
377da1bb401SStefano Zampini    Input Parameters:
378da1bb401SStefano Zampini +  pc - the preconditioning context
379da1bb401SStefano Zampini 
380da1bb401SStefano Zampini    Output Parameters:
381da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
382da1bb401SStefano Zampini 
383da1bb401SStefano Zampini    Level: intermediate
384da1bb401SStefano Zampini 
385da1bb401SStefano Zampini    Notes:
386da1bb401SStefano Zampini 
387da1bb401SStefano Zampini .seealso: PCBDDC
388da1bb401SStefano Zampini @*/
389da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
390da1bb401SStefano Zampini {
391da1bb401SStefano Zampini   PetscErrorCode ierr;
392da1bb401SStefano Zampini 
393da1bb401SStefano Zampini   PetscFunctionBegin;
394da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
395da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
396da1bb401SStefano Zampini   PetscFunctionReturn(0);
397da1bb401SStefano Zampini }
398da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
3991e6b0712SBarry Smith 
400da1bb401SStefano Zampini #undef __FUNCT__
40153cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
40253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
40353cdbc3dSStefano Zampini {
40453cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
40553cdbc3dSStefano Zampini 
40653cdbc3dSStefano Zampini   PetscFunctionBegin;
40753cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
40853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
40953cdbc3dSStefano Zampini }
4101e6b0712SBarry Smith 
41153cdbc3dSStefano Zampini #undef __FUNCT__
41253cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
41353cdbc3dSStefano Zampini /*@
414da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
415da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
41653cdbc3dSStefano Zampini 
4179c0446d6SStefano Zampini    Not collective
41853cdbc3dSStefano Zampini 
41953cdbc3dSStefano Zampini    Input Parameters:
42053cdbc3dSStefano Zampini +  pc - the preconditioning context
42153cdbc3dSStefano Zampini 
42253cdbc3dSStefano Zampini    Output Parameters:
42353cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
42453cdbc3dSStefano Zampini 
42553cdbc3dSStefano Zampini    Level: intermediate
42653cdbc3dSStefano Zampini 
42753cdbc3dSStefano Zampini    Notes:
42853cdbc3dSStefano Zampini 
42953cdbc3dSStefano Zampini .seealso: PCBDDC
43053cdbc3dSStefano Zampini @*/
43153cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
43253cdbc3dSStefano Zampini {
43353cdbc3dSStefano Zampini   PetscErrorCode ierr;
43453cdbc3dSStefano Zampini 
43553cdbc3dSStefano Zampini   PetscFunctionBegin;
43653cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43753cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
4380c7d97c5SJed Brown   PetscFunctionReturn(0);
4390c7d97c5SJed Brown }
44036e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
4411e6b0712SBarry Smith 
44236e030ebSStefano Zampini #undef __FUNCT__
443da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
4441a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
44536e030ebSStefano Zampini {
44636e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
447da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
448da1bb401SStefano Zampini   PetscErrorCode ierr;
44936e030ebSStefano Zampini 
45036e030ebSStefano Zampini   PetscFunctionBegin;
451674ae819SStefano Zampini   /* free old CSR */
452674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
453fb223d50SStefano Zampini   /* TODO: PCBDDCGraphSetAdjacency */
454674ae819SStefano Zampini   /* get CSR into graph structure */
455da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
456674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
457674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
460da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4611a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4621a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
463674ae819SStefano Zampini   }
464575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46536e030ebSStefano Zampini   PetscFunctionReturn(0);
46636e030ebSStefano Zampini }
4671e6b0712SBarry Smith 
46836e030ebSStefano Zampini #undef __FUNCT__
469da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
47036e030ebSStefano Zampini /*@
471da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47236e030ebSStefano Zampini 
47336e030ebSStefano Zampini    Not collective
47436e030ebSStefano Zampini 
47536e030ebSStefano Zampini    Input Parameters:
47636e030ebSStefano Zampini +  pc - the preconditioning context
477da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
478da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
479da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
480da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48136e030ebSStefano Zampini 
48236e030ebSStefano Zampini    Level: intermediate
48336e030ebSStefano Zampini 
48436e030ebSStefano Zampini    Notes:
48536e030ebSStefano Zampini 
48636e030ebSStefano Zampini .seealso: PCBDDC
48736e030ebSStefano Zampini @*/
4881a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
48936e030ebSStefano Zampini {
490575ad6abSStefano Zampini   void (*f)(void) = 0;
49136e030ebSStefano Zampini   PetscErrorCode ierr;
49236e030ebSStefano Zampini 
49336e030ebSStefano Zampini   PetscFunctionBegin;
49436e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
495674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
496674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
497674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
498674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
499da1bb401SStefano Zampini   }
50036e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
501575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
502575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
503575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
504575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
505575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50636e030ebSStefano Zampini   }
50736e030ebSStefano Zampini   PetscFunctionReturn(0);
50836e030ebSStefano Zampini }
5099c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5101e6b0712SBarry Smith 
5119c0446d6SStefano Zampini #undef __FUNCT__
5129c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5139c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5149c0446d6SStefano Zampini {
5159c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5169c0446d6SStefano Zampini   PetscInt i;
5179c0446d6SStefano Zampini   PetscErrorCode ierr;
5189c0446d6SStefano Zampini 
5199c0446d6SStefano Zampini   PetscFunctionBegin;
520da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5219c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5229c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5239c0446d6SStefano Zampini   }
524d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
525da1bb401SStefano Zampini   /* allocate space then set */
5269c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5279c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
528da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
529da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5309c0446d6SStefano Zampini   }
5319c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5329c0446d6SStefano Zampini   PetscFunctionReturn(0);
5339c0446d6SStefano Zampini }
5341e6b0712SBarry Smith 
5359c0446d6SStefano Zampini #undef __FUNCT__
5369c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5379c0446d6SStefano Zampini /*@
538da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5399c0446d6SStefano Zampini 
5409c0446d6SStefano Zampini    Not collective
5419c0446d6SStefano Zampini 
5429c0446d6SStefano Zampini    Input Parameters:
5439c0446d6SStefano Zampini +  pc - the preconditioning context
544da1bb401SStefano Zampini -  n - number of index sets defining the fields
545da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5469c0446d6SStefano Zampini 
5479c0446d6SStefano Zampini    Level: intermediate
5489c0446d6SStefano Zampini 
5499c0446d6SStefano Zampini    Notes:
5509c0446d6SStefano Zampini 
5519c0446d6SStefano Zampini .seealso: PCBDDC
5529c0446d6SStefano Zampini @*/
5539c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5549c0446d6SStefano Zampini {
5559c0446d6SStefano Zampini   PetscErrorCode ierr;
5569c0446d6SStefano Zampini 
5579c0446d6SStefano Zampini   PetscFunctionBegin;
5589c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5599c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5609c0446d6SStefano Zampini   PetscFunctionReturn(0);
5619c0446d6SStefano Zampini }
562da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
563534831adSStefano Zampini #undef __FUNCT__
564534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
565534831adSStefano Zampini /* -------------------------------------------------------------------------- */
566534831adSStefano Zampini /*
567534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
568534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5699c0446d6SStefano Zampini 
570534831adSStefano Zampini    Input Parameter:
571534831adSStefano Zampini +  pc - the preconditioner contex
572534831adSStefano Zampini 
573534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
574534831adSStefano Zampini 
575534831adSStefano Zampini    Notes:
576534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
577534831adSStefano Zampini    the user, but instead is called by KSPSolve().
578534831adSStefano Zampini */
579534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
580534831adSStefano Zampini {
581534831adSStefano Zampini   PetscErrorCode ierr;
582534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
583534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
584534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
585534831adSStefano Zampini   Mat            temp_mat;
5863972b0daSStefano Zampini   IS             dirIS;
5873972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5883972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5893972b0daSStefano Zampini   Vec            used_vec;
5903972b0daSStefano Zampini   PetscBool      guess_nonzero;
591534831adSStefano Zampini 
592534831adSStefano Zampini   PetscFunctionBegin;
59362a6ff1dSStefano Zampini   /* Creates parallel work vectors used in presolve. */
59462a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
59562a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
59662a6ff1dSStefano Zampini   }
59762a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
59862a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
59962a6ff1dSStefano Zampini   }
6003972b0daSStefano Zampini   if (x) {
6013972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
6023972b0daSStefano Zampini     used_vec = x;
6033972b0daSStefano Zampini   } else {
6043972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
6053972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
6063972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6073972b0daSStefano Zampini   }
6083972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6093972b0daSStefano Zampini   if (ksp) {
6103972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6113972b0daSStefano Zampini     if ( !guess_nonzero ) {
6123972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6133972b0daSStefano Zampini     }
6143972b0daSStefano Zampini   }
6153308cffdSStefano Zampini 
61662a6ff1dSStefano Zampini   if (rhs) { /* TODO: wiser handling of rhs removal, which is only needed in case of zeroed rows */
6173972b0daSStefano Zampini     /* store the original rhs */
6183972b0daSStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6193972b0daSStefano Zampini 
6203972b0daSStefano Zampini     /* Take into account zeroed rows -> change rhs and store solution removed */
6213972b0daSStefano Zampini     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6223972b0daSStefano Zampini     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6233972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6243972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6253972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6263972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6273972b0daSStefano Zampini     ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6283972b0daSStefano Zampini     if (dirIS) {
6293972b0daSStefano Zampini       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6303972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6313972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6323972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6332fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6343972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6353972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6363972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6373972b0daSStefano Zampini     }
6383972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6393972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
640b76ba322SStefano Zampini 
6413972b0daSStefano Zampini     /* remove the computed solution from the rhs */
6423972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6433972b0daSStefano Zampini     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6443972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6453308cffdSStefano Zampini   }
646b76ba322SStefano Zampini 
647b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6483972b0daSStefano Zampini   if (x) {
6493972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6503972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
65115aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
652b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
653b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
654b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
655b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
656b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
657b76ba322SStefano Zampini       if (ksp) {
658b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
659b76ba322SStefano Zampini       }
660b76ba322SStefano Zampini     }
6613972b0daSStefano Zampini   }
662b76ba322SStefano Zampini 
663674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
664b76ba322SStefano Zampini     /* swap pointers for local matrices */
665b76ba322SStefano Zampini     temp_mat = matis->A;
666b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
667b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
6683308cffdSStefano Zampini   }
6693308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && rhs) {
670b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
671b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
672b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
673b76ba322SStefano Zampini     /* from original basis to modified basis */
674b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
675b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
676b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
677b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
678674ae819SStefano Zampini   }
6790bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
680d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
681d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
682b76ba322SStefano Zampini   }
6830bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
684534831adSStefano Zampini   PetscFunctionReturn(0);
685534831adSStefano Zampini }
686534831adSStefano Zampini /* -------------------------------------------------------------------------- */
687534831adSStefano Zampini #undef __FUNCT__
688534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
689534831adSStefano Zampini /* -------------------------------------------------------------------------- */
690534831adSStefano Zampini /*
691534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
692534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
693534831adSStefano Zampini 
694534831adSStefano Zampini    Input Parameter:
695534831adSStefano Zampini +  pc - the preconditioner contex
696534831adSStefano Zampini 
697534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
698534831adSStefano Zampini 
699534831adSStefano Zampini    Notes:
700534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
701534831adSStefano Zampini    the user, but instead is called by KSPSolve().
702534831adSStefano Zampini */
703534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
704534831adSStefano Zampini {
705534831adSStefano Zampini   PetscErrorCode ierr;
706534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
707534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
708534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
709534831adSStefano Zampini   Mat            temp_mat;
710534831adSStefano Zampini 
711534831adSStefano Zampini   PetscFunctionBegin;
712674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
713534831adSStefano Zampini     /* swap pointers for local matrices */
714534831adSStefano Zampini     temp_mat = matis->A;
715534831adSStefano Zampini     matis->A = pcbddc->local_mat;
716534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
7173425bc38SStefano Zampini   }
7183308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && x) {
719534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
720534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
721534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
722534831adSStefano Zampini     /* from modified basis to original basis */
723534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
724534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
725534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
726534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
727534831adSStefano Zampini   }
7283972b0daSStefano Zampini   /* add solution removed in presolve */
7293425bc38SStefano Zampini   if (x) {
7303425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7313425bc38SStefano Zampini   }
732fb223d50SStefano Zampini   /* restore rhs to its original state */
733fb223d50SStefano Zampini   if (rhs) {
734fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
735fb223d50SStefano Zampini   }
736534831adSStefano Zampini   PetscFunctionReturn(0);
737534831adSStefano Zampini }
738534831adSStefano Zampini /* -------------------------------------------------------------------------- */
73953cdbc3dSStefano Zampini #undef __FUNCT__
74053cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7410c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7420c7d97c5SJed Brown /*
7430c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7440c7d97c5SJed Brown                   by setting data structures and options.
7450c7d97c5SJed Brown 
7460c7d97c5SJed Brown    Input Parameter:
74753cdbc3dSStefano Zampini +  pc - the preconditioner context
7480c7d97c5SJed Brown 
7490c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7500c7d97c5SJed Brown 
7510c7d97c5SJed Brown    Notes:
7520c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7530c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7540c7d97c5SJed Brown */
75553cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7560c7d97c5SJed Brown {
7570c7d97c5SJed Brown   PetscErrorCode ierr;
7580c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
759674ae819SStefano Zampini   MatStructure   flag;
760674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7610c7d97c5SJed Brown 
7620c7d97c5SJed Brown   PetscFunctionBegin;
763674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7643b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7659c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7660c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7670c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7680c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7693b03a366Sstefano_zampini   /* Get stdout for dbg */
770674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
771ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
772e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
773e269702eSStefano Zampini   }
774674ae819SStefano Zampini   /* first attempt to split work */
775674ae819SStefano Zampini   if (pc->setupcalled) {
776674ae819SStefano Zampini     computeis = PETSC_FALSE;
777674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
778674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
779674ae819SStefano Zampini       computetopography = PETSC_FALSE;
780674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
781674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
782674ae819SStefano Zampini       computetopography = PETSC_FALSE;
783674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
784674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
785674ae819SStefano Zampini       computetopography = PETSC_TRUE;
786674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
787674ae819SStefano Zampini     }
788674ae819SStefano Zampini   } else {
789674ae819SStefano Zampini     computeis = PETSC_TRUE;
790674ae819SStefano Zampini     computetopography = PETSC_TRUE;
791674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
792674ae819SStefano Zampini   }
793674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
794674ae819SStefano Zampini   if (computeis) {
795674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
796674ae819SStefano Zampini   }
797674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
798674ae819SStefano Zampini   if (computetopography) {
799674ae819SStefano Zampini     /* reset data */
800674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
801674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
802674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
803674ae819SStefano Zampini   }
804674ae819SStefano Zampini   if (computesolvers) {
805674ae819SStefano Zampini     /* reset data */
806674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
807674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
8080c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
8090c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
810674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
8110c7d97c5SJed Brown   }
8120c7d97c5SJed Brown   PetscFunctionReturn(0);
8130c7d97c5SJed Brown }
8140c7d97c5SJed Brown 
8150c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8160c7d97c5SJed Brown /*
8170c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8180c7d97c5SJed Brown 
8190c7d97c5SJed Brown    Input Parameters:
8200c7d97c5SJed Brown .  pc - the preconditioner context
8210c7d97c5SJed Brown .  r - input vector (global)
8220c7d97c5SJed Brown 
8230c7d97c5SJed Brown    Output Parameter:
8240c7d97c5SJed Brown .  z - output vector (global)
8250c7d97c5SJed Brown 
8260c7d97c5SJed Brown    Application Interface Routine: PCApply()
8270c7d97c5SJed Brown  */
8280c7d97c5SJed Brown #undef __FUNCT__
8290c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
83053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8310c7d97c5SJed Brown {
8320c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8330c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8340c7d97c5SJed Brown   PetscErrorCode    ierr;
8353b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8363b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8372617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8380c7d97c5SJed Brown 
8390c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8400c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
84129622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8420c7d97c5SJed Brown 
8430c7d97c5SJed Brown   PetscFunctionBegin;
84415aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8450c7d97c5SJed Brown     /* First Dirichlet solve */
8460c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8470c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
84853cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8490c7d97c5SJed Brown     /*
8500c7d97c5SJed Brown       Assembling right hand side for BDDC operator
851674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
852674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8530c7d97c5SJed Brown     */
8540c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8550c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
85629622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8570c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8580c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8590c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8600c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
861674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
862b76ba322SStefano Zampini   } else {
8630bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
864b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
865674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
866b76ba322SStefano Zampini   }
867b76ba322SStefano Zampini 
8682617d88aSStefano Zampini   /* Apply interface preconditioner
8692617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8702617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8712617d88aSStefano Zampini 
872674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
873674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8740c7d97c5SJed Brown 
8753b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8760c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8770c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8780c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
87929622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
88053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8810c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
88229622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8830c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8840c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8850c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8860c7d97c5SJed Brown   PetscFunctionReturn(0);
8870c7d97c5SJed Brown }
888da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
889674ae819SStefano Zampini 
890da1bb401SStefano Zampini #undef __FUNCT__
891da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
892da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
893da1bb401SStefano Zampini {
894da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
895da1bb401SStefano Zampini   PetscErrorCode ierr;
896da1bb401SStefano Zampini 
897da1bb401SStefano Zampini   PetscFunctionBegin;
898da1bb401SStefano Zampini   /* free data created by PCIS */
899da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
900674ae819SStefano Zampini   /* free BDDC custom data  */
901674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
902674ae819SStefano Zampini   /* destroy objects related to topography */
903674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
904674ae819SStefano Zampini   /* free allocated graph structure */
905da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
906674ae819SStefano Zampini   /* free data for scaling operator */
907674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
908674ae819SStefano Zampini   /* free solvers stuff */
909674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
91033bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
91133bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
912ac78edfcSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
91362a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
91462a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
91562a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
9163425bc38SStefano Zampini   /* remove functions */
917674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
918bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
919bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
920bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
921bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
922bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
923bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
924bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
925bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
926bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
927bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
928bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
929bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
930bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
931674ae819SStefano Zampini   /* Free the private data structure */
932674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
933da1bb401SStefano Zampini   PetscFunctionReturn(0);
934da1bb401SStefano Zampini }
9353425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9361e6b0712SBarry Smith 
9373425bc38SStefano Zampini #undef __FUNCT__
9383425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9393425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9403425bc38SStefano Zampini {
941674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9423425bc38SStefano Zampini   PC_IS*         pcis;
9433425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9443425bc38SStefano Zampini   PetscErrorCode ierr;
9450c7d97c5SJed Brown 
9463425bc38SStefano Zampini   PetscFunctionBegin;
9473425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9483425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9493425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9503425bc38SStefano Zampini 
9513425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9523425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
9533308cffdSStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
9543425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9553425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9563425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
957fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
958fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
9593425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9603425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
961674ae819SStefano Zampini   /* Apply partition of unity */
9623425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
963674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
96429622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9653425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9663425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9673425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9683425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9693425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9703425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9713425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
972674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9733425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9743425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9753425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9763425bc38SStefano Zampini   }
9773425bc38SStefano Zampini   /* BDDC rhs */
9783425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
97929622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9803425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9813425bc38SStefano Zampini   }
9823425bc38SStefano Zampini   /* apply BDDC */
9833425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9843425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9853425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9863425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9873425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9883425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9893425bc38SStefano Zampini   /* restore original rhs */
9903425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9913425bc38SStefano Zampini   PetscFunctionReturn(0);
9923425bc38SStefano Zampini }
9931e6b0712SBarry Smith 
9943425bc38SStefano Zampini #undef __FUNCT__
9953425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9963425bc38SStefano Zampini /*@
9973425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9983425bc38SStefano Zampini 
9993425bc38SStefano Zampini    Collective
10003425bc38SStefano Zampini 
10013425bc38SStefano Zampini    Input Parameters:
10023425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10033425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
10043425bc38SStefano Zampini 
10053425bc38SStefano Zampini    Output Parameters:
10063425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
10073425bc38SStefano Zampini 
10083425bc38SStefano Zampini    Level: developer
10093425bc38SStefano Zampini 
10103425bc38SStefano Zampini    Notes:
10113425bc38SStefano Zampini 
10123425bc38SStefano Zampini .seealso: PCBDDC
10133425bc38SStefano Zampini @*/
10143425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
10153425bc38SStefano Zampini {
1016674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10173425bc38SStefano Zampini   PetscErrorCode ierr;
10183425bc38SStefano Zampini 
10193425bc38SStefano Zampini   PetscFunctionBegin;
10203425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10213425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10223425bc38SStefano Zampini   PetscFunctionReturn(0);
10233425bc38SStefano Zampini }
10243425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10251e6b0712SBarry Smith 
10263425bc38SStefano Zampini #undef __FUNCT__
10273425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10283425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10293425bc38SStefano Zampini {
1030674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10313425bc38SStefano Zampini   PC_IS*         pcis;
10323425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10333425bc38SStefano Zampini   PetscErrorCode ierr;
10343425bc38SStefano Zampini 
10353425bc38SStefano Zampini   PetscFunctionBegin;
10363425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10373425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10383425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10393425bc38SStefano Zampini 
10403425bc38SStefano Zampini   /* apply B_delta^T */
10413425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10423425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10433425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10443425bc38SStefano Zampini   /* compute rhs for BDDC application */
10453425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
104629622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10473425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10483425bc38SStefano Zampini   }
10493425bc38SStefano Zampini   /* apply BDDC */
10503425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10513425bc38SStefano Zampini   /* put values into standard global vector */
10523425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10533425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
105429622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10553425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10563425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10573425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10583425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10593425bc38SStefano Zampini   }
10603425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10613425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10623425bc38SStefano Zampini   /* final change of basis if needed
10633425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10643308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
10653425bc38SStefano Zampini   PetscFunctionReturn(0);
10663425bc38SStefano Zampini }
10671e6b0712SBarry Smith 
10683425bc38SStefano Zampini #undef __FUNCT__
10693425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10703425bc38SStefano Zampini /*@
10713425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10723425bc38SStefano Zampini 
10733425bc38SStefano Zampini    Collective
10743425bc38SStefano Zampini 
10753425bc38SStefano Zampini    Input Parameters:
10763425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10773425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10783425bc38SStefano Zampini 
10793425bc38SStefano Zampini    Output Parameters:
10803425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10813425bc38SStefano Zampini 
10823425bc38SStefano Zampini    Level: developer
10833425bc38SStefano Zampini 
10843425bc38SStefano Zampini    Notes:
10853425bc38SStefano Zampini 
10863425bc38SStefano Zampini .seealso: PCBDDC
10873425bc38SStefano Zampini @*/
10883425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10893425bc38SStefano Zampini {
1090674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10913425bc38SStefano Zampini   PetscErrorCode ierr;
10923425bc38SStefano Zampini 
10933425bc38SStefano Zampini   PetscFunctionBegin;
10943425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10953425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10963425bc38SStefano Zampini   PetscFunctionReturn(0);
10973425bc38SStefano Zampini }
10983425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10991e6b0712SBarry Smith 
1100f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1101f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1102f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1103f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1104674ae819SStefano Zampini 
11053425bc38SStefano Zampini #undef __FUNCT__
11063425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
11073425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11083425bc38SStefano Zampini {
1109674ae819SStefano Zampini 
1110674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
11113425bc38SStefano Zampini   Mat            newmat;
1112674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
11133425bc38SStefano Zampini   PC             newpc;
1114ce94432eSBarry Smith   MPI_Comm       comm;
11153425bc38SStefano Zampini   PetscErrorCode ierr;
11163425bc38SStefano Zampini 
11173425bc38SStefano Zampini   PetscFunctionBegin;
1118ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
11193425bc38SStefano Zampini   /* FETIDP linear matrix */
11203425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11213425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11223425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11233425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11243425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11253425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11263425bc38SStefano Zampini   /* FETIDP preconditioner */
11273425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11283425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11293425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11303425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11313425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11323425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11333425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11343425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11353425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11363425bc38SStefano Zampini   /* return pointers for objects created */
11373425bc38SStefano Zampini   *fetidp_mat=newmat;
11383425bc38SStefano Zampini   *fetidp_pc=newpc;
11393425bc38SStefano Zampini   PetscFunctionReturn(0);
11403425bc38SStefano Zampini }
11411e6b0712SBarry Smith 
11423425bc38SStefano Zampini #undef __FUNCT__
11433425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11443425bc38SStefano Zampini /*@
11453425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11463425bc38SStefano Zampini 
11473425bc38SStefano Zampini    Collective
11483425bc38SStefano Zampini 
11493425bc38SStefano Zampini    Input Parameters:
11503425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11513425bc38SStefano Zampini 
11523425bc38SStefano Zampini    Level: developer
11533425bc38SStefano Zampini 
11543425bc38SStefano Zampini    Notes:
11553425bc38SStefano Zampini 
11563425bc38SStefano Zampini .seealso: PCBDDC
11573425bc38SStefano Zampini @*/
11583425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11593425bc38SStefano Zampini {
11603425bc38SStefano Zampini   PetscErrorCode ierr;
11613425bc38SStefano Zampini 
11623425bc38SStefano Zampini   PetscFunctionBegin;
11633425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11643425bc38SStefano Zampini   if (pc->setupcalled) {
11653425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1166f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11673425bc38SStefano Zampini   PetscFunctionReturn(0);
11683425bc38SStefano Zampini }
11690c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1170da1bb401SStefano Zampini /*MC
1171da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11720c7d97c5SJed Brown 
1173da1bb401SStefano Zampini    Options Database Keys:
1174da1bb401SStefano Zampini .    -pcbddc ??? -
1175da1bb401SStefano Zampini 
1176da1bb401SStefano Zampini    Level: intermediate
1177da1bb401SStefano Zampini 
1178da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1179da1bb401SStefano Zampini 
1180da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1181da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1182da1bb401SStefano Zampini           on the subdomains).
1183da1bb401SStefano Zampini 
1184da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1185da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1186da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1187da1bb401SStefano Zampini 
1188da1bb401SStefano Zampini    Contributed by Stefano Zampini
1189da1bb401SStefano Zampini 
1190da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1191da1bb401SStefano Zampini M*/
1192b2573a8aSBarry Smith 
1193da1bb401SStefano Zampini #undef __FUNCT__
1194da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11958cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1196da1bb401SStefano Zampini {
1197da1bb401SStefano Zampini   PetscErrorCode      ierr;
1198da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1199da1bb401SStefano Zampini 
1200da1bb401SStefano Zampini   PetscFunctionBegin;
1201da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1202da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1203da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1204da1bb401SStefano Zampini 
1205da1bb401SStefano Zampini   /* create PCIS data structure */
1206da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1207da1bb401SStefano Zampini 
1208da1bb401SStefano Zampini   /* BDDC specific */
1209674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
12100bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
12113972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1212534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1213534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1214534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1215674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1216674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1217da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1218da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1219da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1220da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1221da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
122215aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
122315aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
1224da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1225da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1226da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1227da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1228da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1229da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1230da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1231da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1232da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1233da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
123429622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1235da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1236da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1237da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1238da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1239da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1240da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1241da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
12429d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1243da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1244b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12454fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12464fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1247674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1248674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1249da1bb401SStefano Zampini 
1250674ae819SStefano Zampini   /* create local graph structure */
1251674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1252674ae819SStefano Zampini 
1253674ae819SStefano Zampini   /* scaling */
1254674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1255674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1256da1bb401SStefano Zampini 
1257da1bb401SStefano Zampini   /* function pointers */
1258da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1259da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1260da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1261da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1262da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1263da1bb401SStefano Zampini   pc->ops->view                = 0;
1264da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1265da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1266da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1267534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1268534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1269da1bb401SStefano Zampini 
1270da1bb401SStefano Zampini   /* composing function */
1271674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1274bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1275bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1276bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1277bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1278bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1279bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1280bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1281bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1284bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1285da1bb401SStefano Zampini   PetscFunctionReturn(0);
1286da1bb401SStefano Zampini }
12873425bc38SStefano Zampini 
1288da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1289da1bb401SStefano Zampini /* All static functions from now on                                           */
1290da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
129129622bf0SStefano Zampini 
129229622bf0SStefano Zampini #undef __FUNCT__
12934fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12944fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12954fad6a16SStefano Zampini {
12964fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12974fad6a16SStefano Zampini 
12984fad6a16SStefano Zampini   PetscFunctionBegin;
12994fad6a16SStefano Zampini   pcbddc->current_level=level;
13004fad6a16SStefano Zampini   PetscFunctionReturn(0);
13014fad6a16SStefano Zampini }
13023425bc38SStefano Zampini 
13033b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
13040c7d97c5SJed Brown #undef __FUNCT__
13050c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
130653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
13070c7d97c5SJed Brown {
13080c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1309dcedc2aeSStefano Zampini   PetscErrorCode    ierr;
1310dcedc2aeSStefano Zampini 
1311dcedc2aeSStefano Zampini   PetscFunctionBegin;
1312dcedc2aeSStefano Zampini   /* compute matrix after change of basis and extract local submatrices */
1313dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
1314dcedc2aeSStefano Zampini 
1315dcedc2aeSStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1316dcedc2aeSStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1317dcedc2aeSStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1318dcedc2aeSStefano Zampini   }
1319dcedc2aeSStefano Zampini 
1320dcedc2aeSStefano Zampini   /* Allocate needed vectors */
1321dcedc2aeSStefano Zampini   ierr = PCBDDCCreateWorkVectors(pc);CHKERRQ(ierr);
1322dcedc2aeSStefano Zampini 
1323dcedc2aeSStefano Zampini   /* setup local scatters R_to_B and (optionally) R_to_D : PCBDDCCreateWorkVectors should be called first! */
1324*8ce42a96SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1325dcedc2aeSStefano Zampini 
1326dcedc2aeSStefano Zampini   /* setup local solvers ksp_D and ksp_R */
1327*8ce42a96SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc);CHKERRQ(ierr);
1328dcedc2aeSStefano Zampini 
132988ebb749SStefano Zampini   /* setup local correction and local part of coarse basis */
1330*8ce42a96SStefano Zampini   ierr = PCBDDCSetUpCoarseLocal(pc);CHKERRQ(ierr);
1331674ae819SStefano Zampini 
13320c7d97c5SJed Brown   PetscFunctionReturn(0);
13330c7d97c5SJed Brown }
13340c7d97c5SJed Brown 
13350c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13360c7d97c5SJed Brown 
13377cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
13387cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
13397cbb387bSStefano Zampini #include "metis.h"
13407cbb387bSStefano Zampini #define MetisInt    idx_t
13417cbb387bSStefano Zampini #define MetisScalar real_t
13427cbb387bSStefano Zampini #endif
13437cbb387bSStefano Zampini 
13440c7d97c5SJed Brown #undef __FUNCT__
1345674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
134688ebb749SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
13470c7d97c5SJed Brown {
1348674ae819SStefano Zampini 
1349674ae819SStefano Zampini 
13500c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
13510c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
13520c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1353ce94432eSBarry Smith   MPI_Comm  prec_comm;
13540c7d97c5SJed Brown   MPI_Comm  coarse_comm;
13550c7d97c5SJed Brown 
1356674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1357674ae819SStefano Zampini 
13580c7d97c5SJed Brown   /* common to all choiches */
13590c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
13600c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
13610c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
13620c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
13630c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
13640c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
13650c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
13660c7d97c5SJed Brown   PetscMPIInt master_proc=0;
13670c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
13680c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
13695b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
13700c7d97c5SJed Brown   PetscMPIInt count_recv=0;
13715b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
13720c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
13730c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
13740c7d97c5SJed Brown   /* some other variables */
13750c7d97c5SJed Brown   PetscErrorCode ierr;
137619fd82e9SBarry Smith   MatType coarse_mat_type;
137719fd82e9SBarry Smith   PCType  coarse_pc_type;
137819fd82e9SBarry Smith   KSPType coarse_ksp_type;
137953cdbc3dSStefano Zampini   PC pc_temp;
13804fad6a16SStefano Zampini   PetscInt i,j,k;
13813b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1382e269702eSStefano Zampini   /* verbose output viewer */
1383e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
13845b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
1385142dfd88SStefano Zampini 
1386ea7e1babSStefano Zampini   PetscInt      offset,offset2;
1387a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
1388523858cfSStefano Zampini   PetscInt      *dnz,*onz;
1389142dfd88SStefano Zampini 
1390142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
13910c7d97c5SJed Brown 
13920c7d97c5SJed Brown   PetscFunctionBegin;
13934b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
13940c7d97c5SJed Brown   ins_local_primal_indices = 0;
13950c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
13960c7d97c5SJed Brown   localsizes2              = 0;
13970c7d97c5SJed Brown   localdispl2              = 0;
13980c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
13990c7d97c5SJed Brown   coarse_ISLG              = 0;
14000c7d97c5SJed Brown 
140153cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
140253cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
1403142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
1404142dfd88SStefano Zampini 
1405beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1406beed3852SStefano Zampini   {
1407674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
1408ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
1409ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
1410ef028eecSStefano Zampini 
1411ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1412beed3852SStefano Zampini 
1413beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1414ffe5efe1SStefano Zampini     j = 0;
1415142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1416ffe5efe1SStefano Zampini       j = size_prec_comm;
1417ffe5efe1SStefano Zampini     }
1418ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1419ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1420beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
1421142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
14225619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1423ffe5efe1SStefano Zampini     } else {
1424ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1425ffe5efe1SStefano Zampini     }
1426beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1427ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
1428beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1429beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1430beed3852SStefano Zampini     }
1431beed3852SStefano Zampini 
1432da1bb401SStefano Zampini     /* First let's count coarse dofs.
1433beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1434beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1435beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1436ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
1437674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
1438674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
1439674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1440674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
1441674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
1442674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1443ef028eecSStefano Zampini     /* Compute number of coarse dofs */
1444674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
1445ef028eecSStefano Zampini 
1446ef028eecSStefano Zampini     if (dbg_flag) {
14472e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14482e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14492e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
14502e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
14512e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14522fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
1453beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14542e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1455da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1456da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1457da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1458da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1459da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14602e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14612e8d2280SStefano Zampini         if (array[i] == 1.0) {
14622e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
14632e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
14642e8d2280SStefano Zampini         }
14652e8d2280SStefano Zampini       }
14662e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14672e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14685b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
14692e8d2280SStefano Zampini       }
1470da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14712e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1472da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1473da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1474da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
14752e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
14762e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14772e8d2280SStefano Zampini     }
1478142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
14790bdf917eSStefano Zampini   }
14800bdf917eSStefano Zampini 
14812e8d2280SStefano Zampini   if (dbg_flag) {
14827cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
14839d9e44b6SStefano Zampini     if (dbg_flag > 1) {
1484674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
14852e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1486674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1487674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1488674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1489674ae819SStefano Zampini       }
14902e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14912e8d2280SStefano Zampini     }
14922e8d2280SStefano Zampini   }
14932e8d2280SStefano Zampini 
1494a929c220SStefano Zampini   im_active = 0;
14952fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
1496a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
14970bdf917eSStefano Zampini 
14980bdf917eSStefano Zampini   /* adapt coarse problem type */
14997cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
15004fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
15014fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
1502a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
15030bdf917eSStefano Zampini         if (dbg_flag) {
1504a929c220SStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"Not enough active processes on level %d (active %d,ratio %d). Parallel direct solve for coarse problem\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
15050bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
15060bdf917eSStefano Zampini         }
15070bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
1508142dfd88SStefano Zampini       }
15094fad6a16SStefano Zampini     } else {
15104fad6a16SStefano Zampini       if (dbg_flag) {
1511a929c220SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Max number of levels reached. Using parallel direct solve for coarse problem\n",pcbddc->max_levels,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
15124fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
15134fad6a16SStefano Zampini       }
15144fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
15154fad6a16SStefano Zampini     }
15164fad6a16SStefano Zampini   }
15177cbb387bSStefano Zampini #else
15187cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
15197cbb387bSStefano Zampini #endif
1520beed3852SStefano Zampini 
15210c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
15220c7d97c5SJed Brown 
1523da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
15240c7d97c5SJed Brown     {
15257cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
15260c7d97c5SJed Brown       /* we need additional variables */
15270c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15280c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
15290c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
15300c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15310c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15320c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15330c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15340c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15350c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15360c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15370c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15380c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15390c7d97c5SJed Brown       MetisInt    *faces_xadj;
15400c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15410c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15420c7d97c5SJed Brown       PetscInt    *array_int;
15430c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15440c7d97c5SJed Brown       PetscMPIInt total_faces=0;
15453828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
15460c7d97c5SJed Brown 
15470c7d97c5SJed Brown       /* define some quantities */
15480c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15490c7d97c5SJed Brown       coarse_mat_type = MATIS;
15500c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
1551142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
15520c7d97c5SJed Brown 
15530c7d97c5SJed Brown       /* details of coarse decomposition */
1554a929c220SStefano Zampini       n_subdomains = active_procs;
15550c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1556a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
15573828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
15583828260eSStefano Zampini 
1559a929c220SStefano Zampini #if 0
1560a929c220SStefano Zampini       PetscMPIInt *old_ranks;
1561a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
1562a929c220SStefano Zampini       MatPartitioning mat_part;
1563a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
1564a929c220SStefano Zampini       PetscViewer viewer_test;
1565a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
1566a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
1567a929c220SStefano Zampini       Mat         mat_adj;
1568a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
1569a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1570a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
1571a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
1572a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
1573a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
1574a929c220SStefano Zampini       if (im_active) {
1575a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
1576a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
1577a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
1578a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
1579a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
1580674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
1581674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
1582a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
1583a929c220SStefano Zampini         k = pcis->n_neigh-1;
1584a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
1585a929c220SStefano Zampini         ii[0]=0;
1586a929c220SStefano Zampini         ii[1]=k;
1587a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
1588674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
1589a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
15900298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
1591a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
1592a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
1593a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
1594a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
1595a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
1596a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
1597a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
1598a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
1599a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
1600a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
1601a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
1602a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
1603a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
1604a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
1605a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
1606a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
1607a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
1608a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
1609a929c220SStefano Zampini       }
1610a929c220SStefano Zampini #endif
1611a929c220SStefano Zampini 
16124fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
16130c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
16143828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
16150c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
16160c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16170c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
16180c7d97c5SJed Brown         }
16190c7d97c5SJed Brown       }
16200c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16210c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16227cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16230c7d97c5SJed Brown             my_faces++;
16240c7d97c5SJed Brown             break;
16250c7d97c5SJed Brown           }
16260c7d97c5SJed Brown         }
16270c7d97c5SJed Brown       }
16280c7d97c5SJed Brown 
162953cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
16300c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
16310c7d97c5SJed Brown       my_faces=0;
16320c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16330c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16347cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16350c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
16360c7d97c5SJed Brown             my_faces++;
16370c7d97c5SJed Brown             break;
16380c7d97c5SJed Brown           }
16390c7d97c5SJed Brown         }
16400c7d97c5SJed Brown       }
16410c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16420c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
16430c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
16440c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
16450c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
16460c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
16470c7d97c5SJed Brown       }
164853cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16490c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16500c7d97c5SJed Brown         faces_xadj[0]=0;
16510c7d97c5SJed Brown         faces_displacements[0]=0;
16520c7d97c5SJed Brown         j=0;
16530c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
16540c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
16550c7d97c5SJed Brown           if (number_of_faces[i-1]) {
16560c7d97c5SJed Brown             j++;
16570c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
16580c7d97c5SJed Brown           }
16590c7d97c5SJed Brown         }
16600c7d97c5SJed Brown       }
166153cdbc3dSStefano 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);
16620c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
16630c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
16640c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16653828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
16660c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16670c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16680c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16690c7d97c5SJed Brown       }
16700c7d97c5SJed Brown 
16710c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
1672674ae819SStefano Zampini 
16733828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
1674674ae819SStefano Zampini 
16750c7d97c5SJed Brown         ncon=1;
16760c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16770c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16780c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16790c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16800c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16810c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16820c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16834fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
16843828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
16853828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
16863828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16870c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1688674ae819SStefano Zampini             if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetUpCoarseEnvironment\n",ierr);
16893828260eSStefano Zampini           } else {
16903828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1691674ae819SStefano Zampini             if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphRecursive (metis error code %D) called from PCBDDCSetUpCoarseEnvironment\n",ierr);
16923828260eSStefano Zampini           }
16934fad6a16SStefano Zampini         } else {
16942fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
16954fad6a16SStefano Zampini         }
16960c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
16970c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
16980bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
16992fa5cd67SKarl Rupp 
17000c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
17012fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
17022fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
17030c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
17040c7d97c5SJed Brown       }
17050c7d97c5SJed Brown 
17060c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
17070c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
1708da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
1709da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
17100c7d97c5SJed Brown       }
1711da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1712da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
171353cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
17140c7d97c5SJed Brown 
17150c7d97c5SJed Brown       if ( coarse_color == 0 ) {
171653cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
171753cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
17180c7d97c5SJed Brown       } else {
17190c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
17200c7d97c5SJed Brown       }
17210c7d97c5SJed Brown 
17227cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
17230c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
17240c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
17250bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
17260bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
17270c7d97c5SJed Brown         /* some initializations */
17280c7d97c5SJed Brown         displacements_recv[0]=0;
17290bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17300c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
17310bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
17320bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17332fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
17340bdf917eSStefano Zampini           }
17350bdf917eSStefano Zampini         }
17360c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
17372fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
17382fa5cd67SKarl Rupp 
17390c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
17400c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17410c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
17423828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17430c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
17440c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
17453828260eSStefano Zampini               total_count_recv[j]+=1;
17460c7d97c5SJed Brown             }
17470c7d97c5SJed Brown           }
17480c7d97c5SJed Brown         }
1749da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
17503828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
17513828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
17523828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
17533828260eSStefano Zampini           }
17543828260eSStefano Zampini           printf("\n");
1755da1bb401SStefano Zampini         }*/
17560c7d97c5SJed Brown 
17570c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
17580bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
17590bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
17600bdf917eSStefano Zampini         }
1761da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
1762674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
17633828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
17643828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
17653828260eSStefano Zampini           } else {
17663828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
17673828260eSStefano Zampini           }
1768da1bb401SStefano Zampini         printf("\n");*/
17690c7d97c5SJed Brown       }
17700c7d97c5SJed Brown 
17710c7d97c5SJed Brown       /* Scatter new decomposition for send details */
177253cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
17730c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17740c7d97c5SJed Brown       if ( coarse_color == 0) {
177553cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17760c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
177753cdbc3dSStefano 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);
17780c7d97c5SJed Brown       }
17790c7d97c5SJed Brown 
1780da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
1781da1bb401SStefano Zampini       if (coarse_color == 0) {
1782da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
1783da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
1784da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
1785da1bb401SStefano Zampini         printf("\n");
1786da1bb401SStefano Zampini       }*/
17870c7d97c5SJed Brown 
17880c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
17890bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
1790da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17910bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17920c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17930c7d97c5SJed Brown       }
17947cbb387bSStefano Zampini #endif
17950c7d97c5SJed Brown       break;
17960c7d97c5SJed Brown     }
17970c7d97c5SJed Brown 
17980c7d97c5SJed Brown     case(REPLICATED_BDDC):
17990c7d97c5SJed Brown 
18000c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
18010c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
18020c7d97c5SJed Brown       coarse_pc_type  = PCLU;
180353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18040c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18050c7d97c5SJed Brown       active_rank = rank_prec_comm;
18060c7d97c5SJed Brown       break;
18070c7d97c5SJed Brown 
18080c7d97c5SJed Brown     case(PARALLEL_BDDC):
18090c7d97c5SJed Brown 
18100c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1811674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18120c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
181353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18140c7d97c5SJed Brown       coarse_comm = prec_comm;
18150c7d97c5SJed Brown       active_rank = rank_prec_comm;
18160c7d97c5SJed Brown       break;
18170c7d97c5SJed Brown 
18180c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
18190c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
1820674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18210c7d97c5SJed Brown       coarse_pc_type = PCLU;
182253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18230c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18240c7d97c5SJed Brown       active_rank = master_proc;
18250c7d97c5SJed Brown       break;
18260c7d97c5SJed Brown   }
18270c7d97c5SJed Brown 
18280c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
18290c7d97c5SJed Brown 
18300c7d97c5SJed Brown     case(SCATTERS_BDDC):
18310c7d97c5SJed Brown       {
18320c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
18330c7d97c5SJed Brown 
18342e8d2280SStefano Zampini           IS coarse_IS;
18352e8d2280SStefano Zampini 
1836523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
1837523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
1838523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
1839523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
1840523858cfSStefano Zampini             /* nonzeros */
1841523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1842523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
1843523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1844523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
1845523858cfSStefano Zampini             }
1846523858cfSStefano Zampini           } else {
18470c7d97c5SJed Brown             PetscMPIInt send_size;
1848ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
18490c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
18500c7d97c5SJed Brown             PetscInt    ii,jj;
18510c7d97c5SJed Brown             MPI_Request *requests;
1852ef028eecSStefano Zampini 
1853523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
1854523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
1855523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
1856523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1857523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
1858523858cfSStefano Zampini             j = 0;
1859523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1860523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
1861523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
1862523858cfSStefano Zampini             }
1863523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
1864523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
18650c7d97c5SJed Brown             /* allocate auxiliary space */
1866523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
18670c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
18680c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
18690c7d97c5SJed Brown             /* allocate stuffs for message massing */
18700c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
1871523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
1872523858cfSStefano Zampini             /* send indices to be inserted */
1873523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1874523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
1875523858cfSStefano Zampini               ierr = MPI_Irecv(&pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]],send_size,MPIU_INT,ranks_recv[i],999,prec_comm,&requests[i]);CHKERRQ(ierr);
1876523858cfSStefano Zampini             }
1877523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1878523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
1879ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
1880ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
1881ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
1882ef028eecSStefano Zampini               }
1883ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
1884523858cfSStefano Zampini             }
1885523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1886ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1887ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
1888ef028eecSStefano Zampini             }
18890c7d97c5SJed Brown             j = 0;
18900c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
18912e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
18922e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
18930c7d97c5SJed Brown               localdispl2[i] = j;
18940c7d97c5SJed Brown               j += localsizes2[i];
1895523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
18964fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
18972e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
18984fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
18990c7d97c5SJed Brown               }
19004fad6a16SStefano Zampini             }
1901523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
19020c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19030c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
19040c7d97c5SJed Brown             ins_local_primal_size = 0;
1905ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
1906ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
19070c7d97c5SJed Brown                 ins_local_primal_size++;
1908ea7e1babSStefano Zampini               }
1909ea7e1babSStefano Zampini             }
19100c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
19110c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19120c7d97c5SJed Brown             j = 0;
1913ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
1914ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
19152e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
19162e8d2280SStefano Zampini                 j++;
1917ea7e1babSStefano Zampini               }
1918ea7e1babSStefano Zampini             }
1919523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
1920523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1921523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
1922523858cfSStefano Zampini             }
1923523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1924523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
1925523858cfSStefano 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);
1926523858cfSStefano Zampini             }
1927523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1928523858cfSStefano Zampini             /* nonzeros */
1929523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1930523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
19310c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
19320c7d97c5SJed Brown             j=0;
19330c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
19340c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
19350c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
19360c7d97c5SJed Brown               } else {
19370c7d97c5SJed Brown                 aux_ins_indices[i]=j;
19380c7d97c5SJed Brown                 j++;
19390c7d97c5SJed Brown               }
19400c7d97c5SJed Brown             }
19414fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
1942523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
1943523858cfSStefano Zampini               for (k=0;k<j;k++) {
1944523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
19450c7d97c5SJed Brown               }
19460c7d97c5SJed Brown             }
1947523858cfSStefano Zampini             /* check */
1948523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1949523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
1950523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
19510c7d97c5SJed Brown               }
19520c7d97c5SJed Brown             }
19530c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
19540c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
19550c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
19564fad6a16SStefano Zampini           }
19570c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
1958142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
19590c7d97c5SJed Brown           coarse_comm = prec_comm;
19600c7d97c5SJed Brown           active_rank = rank_prec_comm;
19610c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
19620c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
19630c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
19642e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
19650c7d97c5SJed Brown           /* arrays for values insertion */
19660c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
19672e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19680c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19690c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
19700c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
19714fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
19724fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
19734fad6a16SStefano Zampini             }
19740c7d97c5SJed Brown           }
19750c7d97c5SJed Brown         }
19760c7d97c5SJed Brown         break;
1977674ae819SStefano Zampini 
19780c7d97c5SJed Brown     }
19790c7d97c5SJed Brown 
19800c7d97c5SJed Brown     case(GATHERS_BDDC):
19810c7d97c5SJed Brown       {
1982674ae819SStefano Zampini 
19830c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
1984ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
19850c7d97c5SJed Brown 
19860c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
19870c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19880bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
19890c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19900c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19910c7d97c5SJed Brown           /* arrays for values insertion */
19922fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19930c7d97c5SJed Brown           localdispl2[0]=0;
19942fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
19950c7d97c5SJed Brown           j=0;
19962fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
19970c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19980c7d97c5SJed Brown         }
19990c7d97c5SJed Brown 
20000c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
20010c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2002ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
20032fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
20042fa5cd67SKarl Rupp 
20050c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2006ef028eecSStefano Zampini           ierr = MPI_Gatherv(send_buffer,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);
200753cdbc3dSStefano 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);
20080c7d97c5SJed Brown         } else {
2009ef028eecSStefano Zampini           ierr = MPI_Allgatherv(send_buffer,mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
201053cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
20110c7d97c5SJed Brown         }
2012ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
20130c7d97c5SJed Brown         break;
2014da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
20150c7d97c5SJed Brown   }
20160c7d97c5SJed Brown 
20170c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
20180c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2019142dfd88SStefano Zampini 
2020142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2021142dfd88SStefano Zampini 
20220c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
20230c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
20240c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
20250c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2026674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2027674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20283b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2029da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
20303b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20310c7d97c5SJed Brown     } else {
20324fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
20333b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
20340c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2035674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2036674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20373b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2038da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2039a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20400c7d97c5SJed Brown     }
2041142dfd88SStefano Zampini     /* preallocation */
2042142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2043ef028eecSStefano Zampini 
2044674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2045ef028eecSStefano Zampini 
2046142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2047142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2048674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2049ef028eecSStefano Zampini 
2050142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2051ef028eecSStefano Zampini 
2052ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2053ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2054ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2055ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2056ef028eecSStefano Zampini 
2057ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2058674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2059ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2060ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2061ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2062ef028eecSStefano Zampini 
2063ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2064ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2065ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2066ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2067ef028eecSStefano Zampini 
2068ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2069ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2070142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2071ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2072ef028eecSStefano Zampini             row_ownership[j]=i;
2073142dfd88SStefano Zampini           }
2074142dfd88SStefano Zampini         }
2075ef028eecSStefano Zampini 
2076ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2077ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2078ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2079ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2080ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2081ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2082ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2083ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2084142dfd88SStefano Zampini             } else {
2085ef028eecSStefano Zampini               my_onz[i] += 1.0;
2086142dfd88SStefano Zampini             }
2087ef028eecSStefano Zampini             if (i != j) {
2088ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2089ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2090ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2091142dfd88SStefano Zampini               } else {
2092ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2093142dfd88SStefano Zampini               }
2094142dfd88SStefano Zampini             }
2095142dfd88SStefano Zampini           }
2096142dfd88SStefano Zampini         }
2097ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2098ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2099a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2100ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2101ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2102a929c220SStefano Zampini         }
2103ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2104ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2105ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2106ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2107ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2108ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
21095b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
21102fa5cd67SKarl Rupp 
2111ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2112ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
21135b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
21142fa5cd67SKarl Rupp 
2115ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2116ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2117ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2118ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2119ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2120ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2121142dfd88SStefano Zampini       } else {
2122142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2123142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2124142dfd88SStefano Zampini           offset2=localdispl2[k];
2125142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2126ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2127ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2128ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2129ef028eecSStefano Zampini           }
2130142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2131142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2132142dfd88SStefano Zampini           }
2133ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2134142dfd88SStefano Zampini         }
2135142dfd88SStefano Zampini       }
21362fa5cd67SKarl Rupp 
2137142dfd88SStefano Zampini       /* check */
2138142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
21392fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
21402fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2141142dfd88SStefano Zampini       }
2142d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2143d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2144142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2145142dfd88SStefano Zampini     } else {
2146523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2147523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2148142dfd88SStefano Zampini     }
2149142dfd88SStefano Zampini     /* insert values */
2150523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
21510c7d97c5SJed 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);
2152523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2153523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2154523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2155523858cfSStefano Zampini         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,INSERT_VALUES);CHKERRQ(ierr);
2156523858cfSStefano Zampini       } else {
2157523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2158523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2159523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2160523858cfSStefano Zampini           offset2 = localdispl2[k];
2161523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2162ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2163ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2164ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2165ef028eecSStefano Zampini           }
2166523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2167523858cfSStefano Zampini           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);
2168ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2169523858cfSStefano Zampini         }
2170523858cfSStefano Zampini       }
2171523858cfSStefano Zampini       ins_local_primal_indices = 0;
2172523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2173ea7e1babSStefano Zampini     } else {
2174ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2175ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2176ea7e1babSStefano Zampini         offset2=localdispl2[k];
2177ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2178ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2179ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2180ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2181ef028eecSStefano Zampini         }
2182ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2183ea7e1babSStefano Zampini         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);
2184ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2185ea7e1babSStefano Zampini       }
2186ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2187ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2188ea7e1babSStefano Zampini     }
21890c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21900c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2191142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2192142dfd88SStefano Zampini     if (issym) {
2193142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2194142dfd88SStefano Zampini     }
21950c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
21960bdf917eSStefano Zampini   }
21970bdf917eSStefano Zampini 
21980bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
21990bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
22000bdf917eSStefano Zampini      IS local_IS,global_IS;
22010bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
22020bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
22030bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
22040bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
22050bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
22060bdf917eSStefano Zampini   }
22070bdf917eSStefano Zampini 
2208a929c220SStefano Zampini   /* free memory no longer needed */
2209a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2210a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2211a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2212a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2213a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2214a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2215a929c220SStefano Zampini 
2216674ae819SStefano Zampini   /* Compute coarse null space */
2217674ae819SStefano Zampini   CoarseNullSpace = 0;
22180bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2219674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
22200bdf917eSStefano Zampini   }
22210bdf917eSStefano Zampini 
22220bdf917eSStefano Zampini   /* KSP for coarse problem */
22230bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
22242e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
22250bdf917eSStefano Zampini 
222653cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
222753cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
222853cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22293b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
223053cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
223153cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
223253cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
22330c7d97c5SJed Brown     /* Allow user's customization */
2234da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
22350c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
223653cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22374fad6a16SStefano Zampini       i = pcbddc->current_level+1;
22384fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
22394fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
22404fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
224153cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2242674ae819SStefano Zampini       if (CoarseNullSpace) {
2243674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2244674ae819SStefano Zampini       }
22454fad6a16SStefano Zampini       if (dbg_flag) {
22464fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
22474fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
224853cdbc3dSStefano Zampini       }
2249674ae819SStefano Zampini     } else {
2250674ae819SStefano Zampini       if (CoarseNullSpace) {
2251674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2252674ae819SStefano Zampini       }
22534fad6a16SStefano Zampini     }
22544fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
225553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2256142dfd88SStefano Zampini 
22570298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
22582e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
22592e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
22602e8d2280SStefano Zampini     if (j == 1) {
22612e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
22622e8d2280SStefano Zampini       if (isbddc) {
22632e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
22645619798eSStefano Zampini       }
22655619798eSStefano Zampini     }
22660c7d97c5SJed Brown   }
2267a929c220SStefano Zampini   /* Check coarse problem if requested */
2268142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2269142dfd88SStefano Zampini     KSP check_ksp;
2270142dfd88SStefano Zampini     PC  check_pc;
2271142dfd88SStefano Zampini     Vec check_vec;
2272142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
227319fd82e9SBarry Smith     KSPType check_ksp_type;
22740c7d97c5SJed Brown 
2275142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2276142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2277142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22780bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2279142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22802fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
22812fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2282142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2283142dfd88SStefano Zampini     } else {
2284142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2285142dfd88SStefano Zampini     }
2286142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2287142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2288142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2289142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2290142dfd88SStefano Zampini     /* create random vec */
2291142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
22920298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2293674ae819SStefano Zampini     if (CoarseNullSpace) {
22941cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
2295674ae819SStefano Zampini     }
2296142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2297142dfd88SStefano Zampini     /* solve coarse problem */
2298142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2299674ae819SStefano Zampini     if (CoarseNullSpace) {
23001cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
2301674ae819SStefano Zampini     }
2302142dfd88SStefano Zampini     /* check coarse problem residual error */
2303142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2304142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2305142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2306142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2307142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2308142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2309142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2310142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2311142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2312142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2313e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
23143b03a366Sstefano_zampini     }
2315142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2316142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2317142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
231853cdbc3dSStefano Zampini   }
2319674ae819SStefano Zampini   if (dbg_flag) {
2320da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2321da1bb401SStefano Zampini   }
2322674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2323a0ba757dSStefano Zampini 
23240c7d97c5SJed Brown   PetscFunctionReturn(0);
23250c7d97c5SJed Brown }
23260c7d97c5SJed Brown 
2327