xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 88ebb7492cd0215be3d18dc7a81e485fff46f8ca)
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_IS*            pcis = (PC_IS*)(pc->data);
13090c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
13100c7d97c5SJed Brown   IS                is_R_local;
1311dcedc2aeSStefano Zampini   PetscErrorCode    ierr;
1312dcedc2aeSStefano Zampini 
1313dcedc2aeSStefano Zampini   PetscFunctionBegin;
1314dcedc2aeSStefano Zampini   /* compute matrix after change of basis and extract local submatrices */
1315dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
1316dcedc2aeSStefano Zampini 
1317dcedc2aeSStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1318dcedc2aeSStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1319dcedc2aeSStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1320dcedc2aeSStefano Zampini   }
1321dcedc2aeSStefano Zampini 
1322dcedc2aeSStefano Zampini   /* Allocate needed vectors */
1323dcedc2aeSStefano Zampini   ierr = PCBDDCCreateWorkVectors(pc);CHKERRQ(ierr);
1324dcedc2aeSStefano Zampini 
1325dcedc2aeSStefano Zampini   /* setup local scatters R_to_B and (optionally) R_to_D : PCBDDCCreateWorkVectors should be called first! */
1326dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc,&is_R_local);CHKERRQ(ierr);
1327dcedc2aeSStefano Zampini 
1328dcedc2aeSStefano Zampini   /* setup local solvers ksp_D and ksp_R */
1329dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,pcis->is_I_local,is_R_local);CHKERRQ(ierr);
1330dcedc2aeSStefano Zampini 
1331*88ebb749SStefano Zampini   /* setup local correction and local part of coarse basis */
1332*88ebb749SStefano Zampini   ierr = PCBDDCSetUpCorrectionAndBasis(pc,is_R_local);CHKERRQ(ierr);
13330c7d97c5SJed Brown 
13340c7d97c5SJed Brown   /* free memory */
13350c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1336674ae819SStefano Zampini 
13370c7d97c5SJed Brown   PetscFunctionReturn(0);
13380c7d97c5SJed Brown }
13390c7d97c5SJed Brown 
13400c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13410c7d97c5SJed Brown 
13427cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
13437cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
13447cbb387bSStefano Zampini #include "metis.h"
13457cbb387bSStefano Zampini #define MetisInt    idx_t
13467cbb387bSStefano Zampini #define MetisScalar real_t
13477cbb387bSStefano Zampini #endif
13487cbb387bSStefano Zampini 
13490c7d97c5SJed Brown #undef __FUNCT__
1350674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
1351*88ebb749SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
13520c7d97c5SJed Brown {
1353674ae819SStefano Zampini 
1354674ae819SStefano Zampini 
13550c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
13560c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
13570c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1358ce94432eSBarry Smith   MPI_Comm  prec_comm;
13590c7d97c5SJed Brown   MPI_Comm  coarse_comm;
13600c7d97c5SJed Brown 
1361674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1362674ae819SStefano Zampini 
13630c7d97c5SJed Brown   /* common to all choiches */
13640c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
13650c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
13660c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
13670c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
13680c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
13690c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
13700c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
13710c7d97c5SJed Brown   PetscMPIInt master_proc=0;
13720c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
13730c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
13745b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
13750c7d97c5SJed Brown   PetscMPIInt count_recv=0;
13765b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
13770c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
13780c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
13790c7d97c5SJed Brown   /* some other variables */
13800c7d97c5SJed Brown   PetscErrorCode ierr;
138119fd82e9SBarry Smith   MatType coarse_mat_type;
138219fd82e9SBarry Smith   PCType  coarse_pc_type;
138319fd82e9SBarry Smith   KSPType coarse_ksp_type;
138453cdbc3dSStefano Zampini   PC pc_temp;
13854fad6a16SStefano Zampini   PetscInt i,j,k;
13863b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1387e269702eSStefano Zampini   /* verbose output viewer */
1388e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
13895b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
1390142dfd88SStefano Zampini 
1391ea7e1babSStefano Zampini   PetscInt      offset,offset2;
1392a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
1393523858cfSStefano Zampini   PetscInt      *dnz,*onz;
1394142dfd88SStefano Zampini 
1395142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
13960c7d97c5SJed Brown 
13970c7d97c5SJed Brown   PetscFunctionBegin;
13984b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
13990c7d97c5SJed Brown   ins_local_primal_indices = 0;
14000c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
14010c7d97c5SJed Brown   localsizes2              = 0;
14020c7d97c5SJed Brown   localdispl2              = 0;
14030c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
14040c7d97c5SJed Brown   coarse_ISLG              = 0;
14050c7d97c5SJed Brown 
140653cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
140753cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
1408142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
1409142dfd88SStefano Zampini 
1410beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1411beed3852SStefano Zampini   {
1412674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
1413ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
1414ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
1415ef028eecSStefano Zampini 
1416ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1417beed3852SStefano Zampini 
1418beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1419ffe5efe1SStefano Zampini     j = 0;
1420142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1421ffe5efe1SStefano Zampini       j = size_prec_comm;
1422ffe5efe1SStefano Zampini     }
1423ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1424ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1425beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
1426142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
14275619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1428ffe5efe1SStefano Zampini     } else {
1429ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1430ffe5efe1SStefano Zampini     }
1431beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1432ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
1433beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1434beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1435beed3852SStefano Zampini     }
1436beed3852SStefano Zampini 
1437da1bb401SStefano Zampini     /* First let's count coarse dofs.
1438beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1439beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1440beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1441ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
1442674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
1443674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
1444674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1445674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
1446674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
1447674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1448ef028eecSStefano Zampini     /* Compute number of coarse dofs */
1449674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
1450ef028eecSStefano Zampini 
1451ef028eecSStefano Zampini     if (dbg_flag) {
14522e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14532e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14542e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
14552e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
14562e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14572fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
1458beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14592e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1460da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1461da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1462da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1463da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1464da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14652e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14662e8d2280SStefano Zampini         if (array[i] == 1.0) {
14672e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
14682e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
14692e8d2280SStefano Zampini         }
14702e8d2280SStefano Zampini       }
14712e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14722e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14735b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
14742e8d2280SStefano Zampini       }
1475da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14762e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1477da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1478da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1479da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
14802e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
14812e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14822e8d2280SStefano Zampini     }
1483142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
14840bdf917eSStefano Zampini   }
14850bdf917eSStefano Zampini 
14862e8d2280SStefano Zampini   if (dbg_flag) {
14877cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
14889d9e44b6SStefano Zampini     if (dbg_flag > 1) {
1489674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
14902e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1491674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1492674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1493674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1494674ae819SStefano Zampini       }
14952e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14962e8d2280SStefano Zampini     }
14972e8d2280SStefano Zampini   }
14982e8d2280SStefano Zampini 
1499a929c220SStefano Zampini   im_active = 0;
15002fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
1501a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
15020bdf917eSStefano Zampini 
15030bdf917eSStefano Zampini   /* adapt coarse problem type */
15047cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
15054fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
15064fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
1507a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
15080bdf917eSStefano Zampini         if (dbg_flag) {
1509a929c220SStefano 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);
15100bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
15110bdf917eSStefano Zampini         }
15120bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
1513142dfd88SStefano Zampini       }
15144fad6a16SStefano Zampini     } else {
15154fad6a16SStefano Zampini       if (dbg_flag) {
1516a929c220SStefano 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);
15174fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
15184fad6a16SStefano Zampini       }
15194fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
15204fad6a16SStefano Zampini     }
15214fad6a16SStefano Zampini   }
15227cbb387bSStefano Zampini #else
15237cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
15247cbb387bSStefano Zampini #endif
1525beed3852SStefano Zampini 
15260c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
15270c7d97c5SJed Brown 
1528da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
15290c7d97c5SJed Brown     {
15307cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
15310c7d97c5SJed Brown       /* we need additional variables */
15320c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15330c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
15340c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
15350c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15360c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15370c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15380c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15390c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15400c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15410c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15420c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15430c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15440c7d97c5SJed Brown       MetisInt    *faces_xadj;
15450c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15460c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15470c7d97c5SJed Brown       PetscInt    *array_int;
15480c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15490c7d97c5SJed Brown       PetscMPIInt total_faces=0;
15503828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
15510c7d97c5SJed Brown 
15520c7d97c5SJed Brown       /* define some quantities */
15530c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15540c7d97c5SJed Brown       coarse_mat_type = MATIS;
15550c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
1556142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
15570c7d97c5SJed Brown 
15580c7d97c5SJed Brown       /* details of coarse decomposition */
1559a929c220SStefano Zampini       n_subdomains = active_procs;
15600c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1561a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
15623828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
15633828260eSStefano Zampini 
1564a929c220SStefano Zampini #if 0
1565a929c220SStefano Zampini       PetscMPIInt *old_ranks;
1566a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
1567a929c220SStefano Zampini       MatPartitioning mat_part;
1568a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
1569a929c220SStefano Zampini       PetscViewer viewer_test;
1570a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
1571a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
1572a929c220SStefano Zampini       Mat         mat_adj;
1573a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
1574a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1575a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
1576a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
1577a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
1578a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
1579a929c220SStefano Zampini       if (im_active) {
1580a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
1581a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
1582a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
1583a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
1584a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
1585674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
1586674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
1587a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
1588a929c220SStefano Zampini         k = pcis->n_neigh-1;
1589a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
1590a929c220SStefano Zampini         ii[0]=0;
1591a929c220SStefano Zampini         ii[1]=k;
1592a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
1593674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
1594a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
15950298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
1596a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
1597a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
1598a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
1599a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
1600a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
1601a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
1602a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
1603a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
1604a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
1605a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
1606a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
1607a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
1608a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
1609a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
1610a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
1611a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
1612a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
1613a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
1614a929c220SStefano Zampini       }
1615a929c220SStefano Zampini #endif
1616a929c220SStefano Zampini 
16174fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
16180c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
16193828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
16200c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
16210c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16220c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
16230c7d97c5SJed Brown         }
16240c7d97c5SJed Brown       }
16250c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16260c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16277cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16280c7d97c5SJed Brown             my_faces++;
16290c7d97c5SJed Brown             break;
16300c7d97c5SJed Brown           }
16310c7d97c5SJed Brown         }
16320c7d97c5SJed Brown       }
16330c7d97c5SJed Brown 
163453cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
16350c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
16360c7d97c5SJed Brown       my_faces=0;
16370c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16380c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16397cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16400c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
16410c7d97c5SJed Brown             my_faces++;
16420c7d97c5SJed Brown             break;
16430c7d97c5SJed Brown           }
16440c7d97c5SJed Brown         }
16450c7d97c5SJed Brown       }
16460c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16470c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
16480c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
16490c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
16500c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
16510c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
16520c7d97c5SJed Brown       }
165353cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16540c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16550c7d97c5SJed Brown         faces_xadj[0]=0;
16560c7d97c5SJed Brown         faces_displacements[0]=0;
16570c7d97c5SJed Brown         j=0;
16580c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
16590c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
16600c7d97c5SJed Brown           if (number_of_faces[i-1]) {
16610c7d97c5SJed Brown             j++;
16620c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
16630c7d97c5SJed Brown           }
16640c7d97c5SJed Brown         }
16650c7d97c5SJed Brown       }
166653cdbc3dSStefano 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);
16670c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
16680c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
16690c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16703828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
16710c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16720c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16730c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16740c7d97c5SJed Brown       }
16750c7d97c5SJed Brown 
16760c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
1677674ae819SStefano Zampini 
16783828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
1679674ae819SStefano Zampini 
16800c7d97c5SJed Brown         ncon=1;
16810c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16820c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16830c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16840c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16850c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16860c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16870c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16884fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
16893828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
16903828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
16913828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16920c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1693674ae819SStefano 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);
16943828260eSStefano Zampini           } else {
16953828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1696674ae819SStefano 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);
16973828260eSStefano Zampini           }
16984fad6a16SStefano Zampini         } else {
16992fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
17004fad6a16SStefano Zampini         }
17010c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
17020c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
17030bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
17042fa5cd67SKarl Rupp 
17050c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
17062fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
17072fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
17080c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
17090c7d97c5SJed Brown       }
17100c7d97c5SJed Brown 
17110c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
17120c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
1713da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
1714da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
17150c7d97c5SJed Brown       }
1716da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1717da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
171853cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
17190c7d97c5SJed Brown 
17200c7d97c5SJed Brown       if ( coarse_color == 0 ) {
172153cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
172253cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
17230c7d97c5SJed Brown       } else {
17240c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
17250c7d97c5SJed Brown       }
17260c7d97c5SJed Brown 
17277cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
17280c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
17290c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
17300bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
17310bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
17320c7d97c5SJed Brown         /* some initializations */
17330c7d97c5SJed Brown         displacements_recv[0]=0;
17340bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17350c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
17360bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
17370bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17382fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
17390bdf917eSStefano Zampini           }
17400bdf917eSStefano Zampini         }
17410c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
17422fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
17432fa5cd67SKarl Rupp 
17440c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
17450c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17460c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
17473828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17480c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
17490c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
17503828260eSStefano Zampini               total_count_recv[j]+=1;
17510c7d97c5SJed Brown             }
17520c7d97c5SJed Brown           }
17530c7d97c5SJed Brown         }
1754da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
17553828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
17563828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
17573828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
17583828260eSStefano Zampini           }
17593828260eSStefano Zampini           printf("\n");
1760da1bb401SStefano Zampini         }*/
17610c7d97c5SJed Brown 
17620c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
17630bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
17640bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
17650bdf917eSStefano Zampini         }
1766da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
1767674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
17683828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
17693828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
17703828260eSStefano Zampini           } else {
17713828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
17723828260eSStefano Zampini           }
1773da1bb401SStefano Zampini         printf("\n");*/
17740c7d97c5SJed Brown       }
17750c7d97c5SJed Brown 
17760c7d97c5SJed Brown       /* Scatter new decomposition for send details */
177753cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
17780c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17790c7d97c5SJed Brown       if ( coarse_color == 0) {
178053cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17810c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
178253cdbc3dSStefano 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);
17830c7d97c5SJed Brown       }
17840c7d97c5SJed Brown 
1785da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
1786da1bb401SStefano Zampini       if (coarse_color == 0) {
1787da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
1788da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
1789da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
1790da1bb401SStefano Zampini         printf("\n");
1791da1bb401SStefano Zampini       }*/
17920c7d97c5SJed Brown 
17930c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
17940bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
1795da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17960bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17970c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17980c7d97c5SJed Brown       }
17997cbb387bSStefano Zampini #endif
18000c7d97c5SJed Brown       break;
18010c7d97c5SJed Brown     }
18020c7d97c5SJed Brown 
18030c7d97c5SJed Brown     case(REPLICATED_BDDC):
18040c7d97c5SJed Brown 
18050c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
18060c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
18070c7d97c5SJed Brown       coarse_pc_type  = PCLU;
180853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18090c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18100c7d97c5SJed Brown       active_rank = rank_prec_comm;
18110c7d97c5SJed Brown       break;
18120c7d97c5SJed Brown 
18130c7d97c5SJed Brown     case(PARALLEL_BDDC):
18140c7d97c5SJed Brown 
18150c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1816674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18170c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
181853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18190c7d97c5SJed Brown       coarse_comm = prec_comm;
18200c7d97c5SJed Brown       active_rank = rank_prec_comm;
18210c7d97c5SJed Brown       break;
18220c7d97c5SJed Brown 
18230c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
18240c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
1825674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18260c7d97c5SJed Brown       coarse_pc_type = PCLU;
182753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18280c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18290c7d97c5SJed Brown       active_rank = master_proc;
18300c7d97c5SJed Brown       break;
18310c7d97c5SJed Brown   }
18320c7d97c5SJed Brown 
18330c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
18340c7d97c5SJed Brown 
18350c7d97c5SJed Brown     case(SCATTERS_BDDC):
18360c7d97c5SJed Brown       {
18370c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
18380c7d97c5SJed Brown 
18392e8d2280SStefano Zampini           IS coarse_IS;
18402e8d2280SStefano Zampini 
1841523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
1842523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
1843523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
1844523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
1845523858cfSStefano Zampini             /* nonzeros */
1846523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1847523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
1848523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1849523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
1850523858cfSStefano Zampini             }
1851523858cfSStefano Zampini           } else {
18520c7d97c5SJed Brown             PetscMPIInt send_size;
1853ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
18540c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
18550c7d97c5SJed Brown             PetscInt    ii,jj;
18560c7d97c5SJed Brown             MPI_Request *requests;
1857ef028eecSStefano Zampini 
1858523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
1859523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
1860523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
1861523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1862523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
1863523858cfSStefano Zampini             j = 0;
1864523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1865523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
1866523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
1867523858cfSStefano Zampini             }
1868523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
1869523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
18700c7d97c5SJed Brown             /* allocate auxiliary space */
1871523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
18720c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
18730c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
18740c7d97c5SJed Brown             /* allocate stuffs for message massing */
18750c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
1876523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
1877523858cfSStefano Zampini             /* send indices to be inserted */
1878523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1879523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
1880523858cfSStefano 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);
1881523858cfSStefano Zampini             }
1882523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1883523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
1884ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
1885ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
1886ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
1887ef028eecSStefano Zampini               }
1888ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
1889523858cfSStefano Zampini             }
1890523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1891ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1892ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
1893ef028eecSStefano Zampini             }
18940c7d97c5SJed Brown             j = 0;
18950c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
18962e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
18972e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
18980c7d97c5SJed Brown               localdispl2[i] = j;
18990c7d97c5SJed Brown               j += localsizes2[i];
1900523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
19014fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
19022e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
19034fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
19040c7d97c5SJed Brown               }
19054fad6a16SStefano Zampini             }
1906523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
19070c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19080c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
19090c7d97c5SJed Brown             ins_local_primal_size = 0;
1910ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
1911ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
19120c7d97c5SJed Brown                 ins_local_primal_size++;
1913ea7e1babSStefano Zampini               }
1914ea7e1babSStefano Zampini             }
19150c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
19160c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19170c7d97c5SJed Brown             j = 0;
1918ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
1919ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
19202e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
19212e8d2280SStefano Zampini                 j++;
1922ea7e1babSStefano Zampini               }
1923ea7e1babSStefano Zampini             }
1924523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
1925523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1926523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
1927523858cfSStefano Zampini             }
1928523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1929523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
1930523858cfSStefano 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);
1931523858cfSStefano Zampini             }
1932523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1933523858cfSStefano Zampini             /* nonzeros */
1934523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1935523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
19360c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
19370c7d97c5SJed Brown             j=0;
19380c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
19390c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
19400c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
19410c7d97c5SJed Brown               } else {
19420c7d97c5SJed Brown                 aux_ins_indices[i]=j;
19430c7d97c5SJed Brown                 j++;
19440c7d97c5SJed Brown               }
19450c7d97c5SJed Brown             }
19464fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
1947523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
1948523858cfSStefano Zampini               for (k=0;k<j;k++) {
1949523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
19500c7d97c5SJed Brown               }
19510c7d97c5SJed Brown             }
1952523858cfSStefano Zampini             /* check */
1953523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1954523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
1955523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
19560c7d97c5SJed Brown               }
19570c7d97c5SJed Brown             }
19580c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
19590c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
19600c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
19614fad6a16SStefano Zampini           }
19620c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
1963142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
19640c7d97c5SJed Brown           coarse_comm = prec_comm;
19650c7d97c5SJed Brown           active_rank = rank_prec_comm;
19660c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
19670c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
19680c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
19692e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
19700c7d97c5SJed Brown           /* arrays for values insertion */
19710c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
19722e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19730c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19740c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
19750c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
19764fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
19774fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
19784fad6a16SStefano Zampini             }
19790c7d97c5SJed Brown           }
19800c7d97c5SJed Brown         }
19810c7d97c5SJed Brown         break;
1982674ae819SStefano Zampini 
19830c7d97c5SJed Brown     }
19840c7d97c5SJed Brown 
19850c7d97c5SJed Brown     case(GATHERS_BDDC):
19860c7d97c5SJed Brown       {
1987674ae819SStefano Zampini 
19880c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
1989ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
19900c7d97c5SJed Brown 
19910c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
19920c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19930bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
19940c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19950c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19960c7d97c5SJed Brown           /* arrays for values insertion */
19972fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19980c7d97c5SJed Brown           localdispl2[0]=0;
19992fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
20000c7d97c5SJed Brown           j=0;
20012fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
20020c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
20030c7d97c5SJed Brown         }
20040c7d97c5SJed Brown 
20050c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
20060c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2007ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
20082fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
20092fa5cd67SKarl Rupp 
20100c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2011ef028eecSStefano 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);
201253cdbc3dSStefano 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);
20130c7d97c5SJed Brown         } else {
2014ef028eecSStefano 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);
201553cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
20160c7d97c5SJed Brown         }
2017ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
20180c7d97c5SJed Brown         break;
2019da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
20200c7d97c5SJed Brown   }
20210c7d97c5SJed Brown 
20220c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
20230c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2024142dfd88SStefano Zampini 
2025142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2026142dfd88SStefano Zampini 
20270c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
20280c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
20290c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
20300c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2031674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2032674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20333b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2034da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
20353b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20360c7d97c5SJed Brown     } else {
20374fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
20383b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
20390c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2040674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2041674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20423b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2043da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2044a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20450c7d97c5SJed Brown     }
2046142dfd88SStefano Zampini     /* preallocation */
2047142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2048ef028eecSStefano Zampini 
2049674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2050ef028eecSStefano Zampini 
2051142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2052142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2053674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2054ef028eecSStefano Zampini 
2055142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2056ef028eecSStefano Zampini 
2057ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2058ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2059ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2060ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2061ef028eecSStefano Zampini 
2062ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2063674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2064ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2065ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2066ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2067ef028eecSStefano Zampini 
2068ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2069ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2070ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2071ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2072ef028eecSStefano Zampini 
2073ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2074ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2075142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2076ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2077ef028eecSStefano Zampini             row_ownership[j]=i;
2078142dfd88SStefano Zampini           }
2079142dfd88SStefano Zampini         }
2080ef028eecSStefano Zampini 
2081ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2082ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2083ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2084ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2085ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2086ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2087ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2088ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2089142dfd88SStefano Zampini             } else {
2090ef028eecSStefano Zampini               my_onz[i] += 1.0;
2091142dfd88SStefano Zampini             }
2092ef028eecSStefano Zampini             if (i != j) {
2093ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2094ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2095ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2096142dfd88SStefano Zampini               } else {
2097ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2098142dfd88SStefano Zampini               }
2099142dfd88SStefano Zampini             }
2100142dfd88SStefano Zampini           }
2101142dfd88SStefano Zampini         }
2102ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2103ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2104a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2105ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2106ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2107a929c220SStefano Zampini         }
2108ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2109ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2110ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2111ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2112ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2113ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
21145b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
21152fa5cd67SKarl Rupp 
2116ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2117ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
21185b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
21192fa5cd67SKarl Rupp 
2120ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2121ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2122ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2123ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2124ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2125ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2126142dfd88SStefano Zampini       } else {
2127142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2128142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2129142dfd88SStefano Zampini           offset2=localdispl2[k];
2130142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2131ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2132ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2133ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2134ef028eecSStefano Zampini           }
2135142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2136142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2137142dfd88SStefano Zampini           }
2138ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2139142dfd88SStefano Zampini         }
2140142dfd88SStefano Zampini       }
21412fa5cd67SKarl Rupp 
2142142dfd88SStefano Zampini       /* check */
2143142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
21442fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
21452fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2146142dfd88SStefano Zampini       }
2147d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2148d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2149142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2150142dfd88SStefano Zampini     } else {
2151523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2152523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2153142dfd88SStefano Zampini     }
2154142dfd88SStefano Zampini     /* insert values */
2155523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
21560c7d97c5SJed 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);
2157523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2158523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2159523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2160523858cfSStefano 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);
2161523858cfSStefano Zampini       } else {
2162523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2163523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2164523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2165523858cfSStefano Zampini           offset2 = localdispl2[k];
2166523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2167ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2168ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2169ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2170ef028eecSStefano Zampini           }
2171523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2172523858cfSStefano 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);
2173ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2174523858cfSStefano Zampini         }
2175523858cfSStefano Zampini       }
2176523858cfSStefano Zampini       ins_local_primal_indices = 0;
2177523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2178ea7e1babSStefano Zampini     } else {
2179ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2180ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2181ea7e1babSStefano Zampini         offset2=localdispl2[k];
2182ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2183ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2184ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2185ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2186ef028eecSStefano Zampini         }
2187ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2188ea7e1babSStefano 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);
2189ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2190ea7e1babSStefano Zampini       }
2191ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2192ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2193ea7e1babSStefano Zampini     }
21940c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21950c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2196142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2197142dfd88SStefano Zampini     if (issym) {
2198142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2199142dfd88SStefano Zampini     }
22000c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
22010bdf917eSStefano Zampini   }
22020bdf917eSStefano Zampini 
22030bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
22040bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
22050bdf917eSStefano Zampini      IS local_IS,global_IS;
22060bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
22070bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
22080bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
22090bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
22100bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
22110bdf917eSStefano Zampini   }
22120bdf917eSStefano Zampini 
2213a929c220SStefano Zampini   /* free memory no longer needed */
2214a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2215a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2216a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2217a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2218a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2219a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2220a929c220SStefano Zampini 
2221674ae819SStefano Zampini   /* Compute coarse null space */
2222674ae819SStefano Zampini   CoarseNullSpace = 0;
22230bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2224674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
22250bdf917eSStefano Zampini   }
22260bdf917eSStefano Zampini 
22270bdf917eSStefano Zampini   /* KSP for coarse problem */
22280bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
22292e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
22300bdf917eSStefano Zampini 
223153cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
223253cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
223353cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22343b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
223553cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
223653cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
223753cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
22380c7d97c5SJed Brown     /* Allow user's customization */
2239da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
22400c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
224153cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22424fad6a16SStefano Zampini       i = pcbddc->current_level+1;
22434fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
22444fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
22454fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
224653cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2247674ae819SStefano Zampini       if (CoarseNullSpace) {
2248674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2249674ae819SStefano Zampini       }
22504fad6a16SStefano Zampini       if (dbg_flag) {
22514fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
22524fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
225353cdbc3dSStefano Zampini       }
2254674ae819SStefano Zampini     } else {
2255674ae819SStefano Zampini       if (CoarseNullSpace) {
2256674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2257674ae819SStefano Zampini       }
22584fad6a16SStefano Zampini     }
22594fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
226053cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2261142dfd88SStefano Zampini 
22620298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
22632e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
22642e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
22652e8d2280SStefano Zampini     if (j == 1) {
22662e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
22672e8d2280SStefano Zampini       if (isbddc) {
22682e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
22695619798eSStefano Zampini       }
22705619798eSStefano Zampini     }
22710c7d97c5SJed Brown   }
2272a929c220SStefano Zampini   /* Check coarse problem if requested */
2273142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2274142dfd88SStefano Zampini     KSP check_ksp;
2275142dfd88SStefano Zampini     PC  check_pc;
2276142dfd88SStefano Zampini     Vec check_vec;
2277142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
227819fd82e9SBarry Smith     KSPType check_ksp_type;
22790c7d97c5SJed Brown 
2280142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2281142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2282142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22830bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2284142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22852fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
22862fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2287142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2288142dfd88SStefano Zampini     } else {
2289142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2290142dfd88SStefano Zampini     }
2291142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2292142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2293142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2294142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2295142dfd88SStefano Zampini     /* create random vec */
2296142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
22970298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2298674ae819SStefano Zampini     if (CoarseNullSpace) {
22991cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
2300674ae819SStefano Zampini     }
2301142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2302142dfd88SStefano Zampini     /* solve coarse problem */
2303142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2304674ae819SStefano Zampini     if (CoarseNullSpace) {
23051cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
2306674ae819SStefano Zampini     }
2307142dfd88SStefano Zampini     /* check coarse problem residual error */
2308142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2309142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2310142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2311142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2312142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2313142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2314142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2315142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2316142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2317142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2318e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
23193b03a366Sstefano_zampini     }
2320142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2321142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2322142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
232353cdbc3dSStefano Zampini   }
2324674ae819SStefano Zampini   if (dbg_flag) {
2325da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2326da1bb401SStefano Zampini   }
2327674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2328a0ba757dSStefano Zampini 
23290c7d97c5SJed Brown   PetscFunctionReturn(0);
23300c7d97c5SJed Brown }
23310c7d97c5SJed Brown 
2332