xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 9d9e44b646d0e5fe9068ee91ce0972b37bd2c08e)
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 PCBDDCSetUseExactDirichlet(PC,PetscBool);
28674ae819SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC,PetscInt);
29674ae819SStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC);
30674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC,PetscScalar*);
31674ae819SStefano Zampini 
320c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
330c7d97c5SJed Brown #undef __FUNCT__
340c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
350c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
360c7d97c5SJed Brown {
370c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
380c7d97c5SJed Brown   PetscErrorCode ierr;
390c7d97c5SJed Brown 
400c7d97c5SJed Brown   PetscFunctionBegin;
410c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
420c7d97c5SJed Brown   /* Verbose debugging of main data structures */
43*9d9e44b6SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,NULL);CHKERRQ(ierr);
440c7d97c5SJed Brown   /* Some customization for default primal space */
450298fd71SBarry 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);
460298fd71SBarry 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);
470298fd71SBarry 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);
480298fd71SBarry 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);
490c7d97c5SJed Brown   /* Coarse solver context */
506c667b0aSStefano 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 */
510298fd71SBarry 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);
520c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
530298fd71SBarry 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);
54674ae819SStefano 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);
55674ae819SStefano 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);
56674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
57674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
58674ae819SStefano Zampini   }
590298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
600298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
61674ae819SStefano 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);
620c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
630c7d97c5SJed Brown   PetscFunctionReturn(0);
640c7d97c5SJed Brown }
650c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
66674ae819SStefano Zampini #undef __FUNCT__
67674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
68674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
69674ae819SStefano Zampini {
70674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
71674ae819SStefano Zampini   PetscErrorCode ierr;
721e6b0712SBarry Smith 
73674ae819SStefano Zampini   PetscFunctionBegin;
74674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
75674ae819SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
76674ae819SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
77674ae819SStefano Zampini   PetscFunctionReturn(0);
78674ae819SStefano Zampini }
79674ae819SStefano Zampini #undef __FUNCT__
80674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
81674ae819SStefano Zampini /*@
82674ae819SStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC.
83674ae819SStefano Zampini 
84674ae819SStefano Zampini    Not collective
85674ae819SStefano Zampini 
86674ae819SStefano Zampini    Input Parameters:
87674ae819SStefano Zampini +  pc - the preconditioning context
88674ae819SStefano Zampini -  PrimalVertices - index sets of primal vertices in local numbering
89674ae819SStefano Zampini 
90674ae819SStefano Zampini    Level: intermediate
91674ae819SStefano Zampini 
92674ae819SStefano Zampini    Notes:
93674ae819SStefano Zampini 
94674ae819SStefano Zampini .seealso: PCBDDC
95674ae819SStefano Zampini @*/
96674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
97674ae819SStefano Zampini {
98674ae819SStefano Zampini   PetscErrorCode ierr;
99674ae819SStefano Zampini 
100674ae819SStefano Zampini   PetscFunctionBegin;
101674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
102674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
103674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
104674ae819SStefano Zampini   PetscFunctionReturn(0);
105674ae819SStefano Zampini }
106674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
1070c7d97c5SJed Brown #undef __FUNCT__
1080c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
10953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
1100c7d97c5SJed Brown {
1110c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1120c7d97c5SJed Brown 
1130c7d97c5SJed Brown   PetscFunctionBegin;
1140c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
1150c7d97c5SJed Brown   PetscFunctionReturn(0);
1160c7d97c5SJed Brown }
1171e6b0712SBarry Smith 
1180c7d97c5SJed Brown #undef __FUNCT__
1190c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
12053cdbc3dSStefano Zampini /*@
1219c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
12253cdbc3dSStefano Zampini 
1239c0446d6SStefano Zampini    Not collective
12453cdbc3dSStefano Zampini 
12553cdbc3dSStefano Zampini    Input Parameters:
12653cdbc3dSStefano Zampini +  pc - the preconditioning context
12753cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
12853cdbc3dSStefano Zampini 
12953cdbc3dSStefano Zampini    Level: intermediate
13053cdbc3dSStefano Zampini 
13153cdbc3dSStefano Zampini    Notes:
132da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
13353cdbc3dSStefano Zampini 
13453cdbc3dSStefano Zampini .seealso: PCBDDC
13553cdbc3dSStefano Zampini @*/
1360c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
1370c7d97c5SJed Brown {
1380c7d97c5SJed Brown   PetscErrorCode ierr;
1390c7d97c5SJed Brown 
1400c7d97c5SJed Brown   PetscFunctionBegin;
1410c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1420c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
1430c7d97c5SJed Brown   PetscFunctionReturn(0);
1440c7d97c5SJed Brown }
1450c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1460c7d97c5SJed Brown #undef __FUNCT__
1474fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
1484fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
1494fad6a16SStefano Zampini {
1504fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1514fad6a16SStefano Zampini 
1524fad6a16SStefano Zampini   PetscFunctionBegin;
1534fad6a16SStefano Zampini   pcbddc->coarsening_ratio=k;
1544fad6a16SStefano Zampini   PetscFunctionReturn(0);
1554fad6a16SStefano Zampini }
1561e6b0712SBarry Smith 
1574fad6a16SStefano Zampini #undef __FUNCT__
1584fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
1594fad6a16SStefano Zampini /*@
1604fad6a16SStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
1614fad6a16SStefano Zampini 
1624fad6a16SStefano Zampini    Logically collective on PC
1634fad6a16SStefano Zampini 
1644fad6a16SStefano Zampini    Input Parameters:
1654fad6a16SStefano Zampini +  pc - the preconditioning context
1664fad6a16SStefano Zampini -  k - coarsening ratio
1674fad6a16SStefano Zampini 
1684fad6a16SStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
1694fad6a16SStefano Zampini 
1704fad6a16SStefano Zampini    Level: intermediate
1714fad6a16SStefano Zampini 
1724fad6a16SStefano Zampini    Notes:
1734fad6a16SStefano Zampini 
1744fad6a16SStefano Zampini .seealso: PCBDDC
1754fad6a16SStefano Zampini @*/
1764fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
1774fad6a16SStefano Zampini {
1784fad6a16SStefano Zampini   PetscErrorCode ierr;
1794fad6a16SStefano Zampini 
1804fad6a16SStefano Zampini   PetscFunctionBegin;
1814fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1824fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
1834fad6a16SStefano Zampini   PetscFunctionReturn(0);
1844fad6a16SStefano Zampini }
1854fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1861e6b0712SBarry Smith 
1874fad6a16SStefano Zampini #undef __FUNCT__
1884fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
1894fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
1904fad6a16SStefano Zampini {
1914fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1924fad6a16SStefano Zampini 
1934fad6a16SStefano Zampini   PetscFunctionBegin;
1944fad6a16SStefano Zampini   pcbddc->max_levels=max_levels;
1954fad6a16SStefano Zampini   PetscFunctionReturn(0);
1964fad6a16SStefano Zampini }
1971e6b0712SBarry Smith 
1984fad6a16SStefano Zampini #undef __FUNCT__
1994fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels"
2004fad6a16SStefano Zampini /*@
2014fad6a16SStefano Zampini  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
2024fad6a16SStefano Zampini 
2034fad6a16SStefano Zampini    Logically collective on PC
2044fad6a16SStefano Zampini 
2054fad6a16SStefano Zampini    Input Parameters:
2064fad6a16SStefano Zampini +  pc - the preconditioning context
2074fad6a16SStefano Zampini -  max_levels - the maximum number of levels
2084fad6a16SStefano Zampini 
2094fad6a16SStefano Zampini    Default value is 1, i.e. coarse problem will be solved inexactly with one application
2104fad6a16SStefano Zampini    of PCBDDC preconditioner if the multilevel approach is requested.
2114fad6a16SStefano Zampini 
2124fad6a16SStefano Zampini    Level: intermediate
2134fad6a16SStefano Zampini 
2144fad6a16SStefano Zampini    Notes:
2154fad6a16SStefano Zampini 
2164fad6a16SStefano Zampini .seealso: PCBDDC
2174fad6a16SStefano Zampini @*/
2184fad6a16SStefano Zampini PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
2194fad6a16SStefano Zampini {
2204fad6a16SStefano Zampini   PetscErrorCode ierr;
2214fad6a16SStefano Zampini 
2224fad6a16SStefano Zampini   PetscFunctionBegin;
2234fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2244fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
2254fad6a16SStefano Zampini   PetscFunctionReturn(0);
2264fad6a16SStefano Zampini }
2274fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
2281e6b0712SBarry Smith 
2294fad6a16SStefano Zampini #undef __FUNCT__
2300bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
2310bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
2320bdf917eSStefano Zampini {
2330bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2340bdf917eSStefano Zampini   PetscErrorCode ierr;
2350bdf917eSStefano Zampini 
2360bdf917eSStefano Zampini   PetscFunctionBegin;
2370bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
2380bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
2390bdf917eSStefano Zampini   pcbddc->NullSpace=NullSpace;
2400bdf917eSStefano Zampini   PetscFunctionReturn(0);
2410bdf917eSStefano Zampini }
2421e6b0712SBarry Smith 
2430bdf917eSStefano Zampini #undef __FUNCT__
2440bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
2450bdf917eSStefano Zampini /*@
2460bdf917eSStefano Zampini  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
2470bdf917eSStefano Zampini 
2480bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
2490bdf917eSStefano Zampini 
2500bdf917eSStefano Zampini    Input Parameters:
2510bdf917eSStefano Zampini +  pc - the preconditioning context
2520bdf917eSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned.
2530bdf917eSStefano Zampini 
2540bdf917eSStefano Zampini    Level: intermediate
2550bdf917eSStefano Zampini 
2560bdf917eSStefano Zampini    Notes:
2570bdf917eSStefano Zampini 
2580bdf917eSStefano Zampini .seealso: PCBDDC
2590bdf917eSStefano Zampini @*/
2600bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
2610bdf917eSStefano Zampini {
2620bdf917eSStefano Zampini   PetscErrorCode ierr;
2630bdf917eSStefano Zampini 
2640bdf917eSStefano Zampini   PetscFunctionBegin;
2650bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
266674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
2670bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
2680bdf917eSStefano Zampini   PetscFunctionReturn(0);
2690bdf917eSStefano Zampini }
2700bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
2711e6b0712SBarry Smith 
2720bdf917eSStefano Zampini #undef __FUNCT__
2733b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
2743b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
2753b03a366Sstefano_zampini {
2763b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2773b03a366Sstefano_zampini   PetscErrorCode ierr;
2783b03a366Sstefano_zampini 
2793b03a366Sstefano_zampini   PetscFunctionBegin;
2803b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
28136e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
28236e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
2833b03a366Sstefano_zampini   PetscFunctionReturn(0);
2843b03a366Sstefano_zampini }
2851e6b0712SBarry Smith 
2863b03a366Sstefano_zampini #undef __FUNCT__
2873b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
2883b03a366Sstefano_zampini /*@
289da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
290da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
2913b03a366Sstefano_zampini 
2923b03a366Sstefano_zampini    Not collective
2933b03a366Sstefano_zampini 
2943b03a366Sstefano_zampini    Input Parameters:
2953b03a366Sstefano_zampini +  pc - the preconditioning context
2960298fd71SBarry Smith -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL)
2973b03a366Sstefano_zampini 
2983b03a366Sstefano_zampini    Level: intermediate
2993b03a366Sstefano_zampini 
3003b03a366Sstefano_zampini    Notes:
3013b03a366Sstefano_zampini 
3023b03a366Sstefano_zampini .seealso: PCBDDC
3033b03a366Sstefano_zampini @*/
3043b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
3053b03a366Sstefano_zampini {
3063b03a366Sstefano_zampini   PetscErrorCode ierr;
3073b03a366Sstefano_zampini 
3083b03a366Sstefano_zampini   PetscFunctionBegin;
3093b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
310674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
3113b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
3123b03a366Sstefano_zampini   PetscFunctionReturn(0);
3133b03a366Sstefano_zampini }
3143b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
3151e6b0712SBarry Smith 
3163b03a366Sstefano_zampini #undef __FUNCT__
3170c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
31853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
3190c7d97c5SJed Brown {
3200c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
32153cdbc3dSStefano Zampini   PetscErrorCode ierr;
3220c7d97c5SJed Brown 
3230c7d97c5SJed Brown   PetscFunctionBegin;
32453cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
32536e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
32636e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
3270c7d97c5SJed Brown   PetscFunctionReturn(0);
3280c7d97c5SJed Brown }
3291e6b0712SBarry Smith 
3300c7d97c5SJed Brown #undef __FUNCT__
3310c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
33257527edcSJed Brown /*@
333da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
334da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
33557527edcSJed Brown 
3369c0446d6SStefano Zampini    Not collective
33757527edcSJed Brown 
33857527edcSJed Brown    Input Parameters:
33957527edcSJed Brown +  pc - the preconditioning context
3400298fd71SBarry Smith -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL)
34157527edcSJed Brown 
34257527edcSJed Brown    Level: intermediate
34357527edcSJed Brown 
34457527edcSJed Brown    Notes:
34557527edcSJed Brown 
34657527edcSJed Brown .seealso: PCBDDC
34757527edcSJed Brown @*/
34853cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
3490c7d97c5SJed Brown {
3500c7d97c5SJed Brown   PetscErrorCode ierr;
3510c7d97c5SJed Brown 
3520c7d97c5SJed Brown   PetscFunctionBegin;
3530c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
354674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
35553cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
35653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
35753cdbc3dSStefano Zampini }
35853cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
3591e6b0712SBarry Smith 
36053cdbc3dSStefano Zampini #undef __FUNCT__
361da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
362da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
363da1bb401SStefano Zampini {
364da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
365da1bb401SStefano Zampini 
366da1bb401SStefano Zampini   PetscFunctionBegin;
367da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
368da1bb401SStefano Zampini   PetscFunctionReturn(0);
369da1bb401SStefano Zampini }
3701e6b0712SBarry Smith 
371da1bb401SStefano Zampini #undef __FUNCT__
372da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
373da1bb401SStefano Zampini /*@
374da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
375da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
376da1bb401SStefano Zampini 
377da1bb401SStefano Zampini    Not collective
378da1bb401SStefano Zampini 
379da1bb401SStefano Zampini    Input Parameters:
380da1bb401SStefano Zampini +  pc - the preconditioning context
381da1bb401SStefano Zampini 
382da1bb401SStefano Zampini    Output Parameters:
383da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
384da1bb401SStefano Zampini 
385da1bb401SStefano Zampini    Level: intermediate
386da1bb401SStefano Zampini 
387da1bb401SStefano Zampini    Notes:
388da1bb401SStefano Zampini 
389da1bb401SStefano Zampini .seealso: PCBDDC
390da1bb401SStefano Zampini @*/
391da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
392da1bb401SStefano Zampini {
393da1bb401SStefano Zampini   PetscErrorCode ierr;
394da1bb401SStefano Zampini 
395da1bb401SStefano Zampini   PetscFunctionBegin;
396da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
397da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
398da1bb401SStefano Zampini   PetscFunctionReturn(0);
399da1bb401SStefano Zampini }
400da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
4011e6b0712SBarry Smith 
402da1bb401SStefano Zampini #undef __FUNCT__
40353cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
40453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
40553cdbc3dSStefano Zampini {
40653cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
40753cdbc3dSStefano Zampini 
40853cdbc3dSStefano Zampini   PetscFunctionBegin;
40953cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
41053cdbc3dSStefano Zampini   PetscFunctionReturn(0);
41153cdbc3dSStefano Zampini }
4121e6b0712SBarry Smith 
41353cdbc3dSStefano Zampini #undef __FUNCT__
41453cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
41553cdbc3dSStefano Zampini /*@
416da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
417da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
41853cdbc3dSStefano Zampini 
4199c0446d6SStefano Zampini    Not collective
42053cdbc3dSStefano Zampini 
42153cdbc3dSStefano Zampini    Input Parameters:
42253cdbc3dSStefano Zampini +  pc - the preconditioning context
42353cdbc3dSStefano Zampini 
42453cdbc3dSStefano Zampini    Output Parameters:
42553cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
42653cdbc3dSStefano Zampini 
42753cdbc3dSStefano Zampini    Level: intermediate
42853cdbc3dSStefano Zampini 
42953cdbc3dSStefano Zampini    Notes:
43053cdbc3dSStefano Zampini 
43153cdbc3dSStefano Zampini .seealso: PCBDDC
43253cdbc3dSStefano Zampini @*/
43353cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
43453cdbc3dSStefano Zampini {
43553cdbc3dSStefano Zampini   PetscErrorCode ierr;
43653cdbc3dSStefano Zampini 
43753cdbc3dSStefano Zampini   PetscFunctionBegin;
43853cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43953cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
4400c7d97c5SJed Brown   PetscFunctionReturn(0);
4410c7d97c5SJed Brown }
44236e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
4431e6b0712SBarry Smith 
44436e030ebSStefano Zampini #undef __FUNCT__
445da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
4461a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
44736e030ebSStefano Zampini {
44836e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
449da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
450da1bb401SStefano Zampini   PetscErrorCode ierr;
45136e030ebSStefano Zampini 
45236e030ebSStefano Zampini   PetscFunctionBegin;
453674ae819SStefano Zampini   /* free old CSR */
454674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
455674ae819SStefano Zampini   /* get CSR into graph structure */
456da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
457674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
460674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
461da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4621a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4631a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
464674ae819SStefano Zampini   }
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 {
490da1bb401SStefano Zampini   PetscInt       nrows,ncols;
491da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
49236e030ebSStefano Zampini   PetscErrorCode ierr;
49336e030ebSStefano Zampini 
49436e030ebSStefano Zampini   PetscFunctionBegin;
49536e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
496674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
497674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
498674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
499674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
500da1bb401SStefano Zampini   }
501674ae819SStefano Zampini   /* pcis info could not be available at this point */
502674ae819SStefano Zampini   ierr = MatGetSize(matis->A,&nrows,&ncols);CHKERRQ(ierr);
503674ae819SStefano Zampini   if (nvtxs != nrows) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local adjacency size %d passed in %s differs from local problem size %d!\n",nvtxs,__FUNCT__,nrows);
504674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
50536e030ebSStefano Zampini   PetscFunctionReturn(0);
50636e030ebSStefano Zampini }
5079c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5081e6b0712SBarry Smith 
5099c0446d6SStefano Zampini #undef __FUNCT__
5109c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5119c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5129c0446d6SStefano Zampini {
5139c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5149c0446d6SStefano Zampini   PetscInt i;
5159c0446d6SStefano Zampini   PetscErrorCode ierr;
5169c0446d6SStefano Zampini 
5179c0446d6SStefano Zampini   PetscFunctionBegin;
518da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5199c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5209c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5219c0446d6SStefano Zampini   }
522d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
523da1bb401SStefano Zampini   /* allocate space then set */
5249c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5259c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
526da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
527da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5289c0446d6SStefano Zampini   }
5299c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5309c0446d6SStefano Zampini   PetscFunctionReturn(0);
5319c0446d6SStefano Zampini }
5321e6b0712SBarry Smith 
5339c0446d6SStefano Zampini #undef __FUNCT__
5349c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5359c0446d6SStefano Zampini /*@
536da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5379c0446d6SStefano Zampini 
5389c0446d6SStefano Zampini    Not collective
5399c0446d6SStefano Zampini 
5409c0446d6SStefano Zampini    Input Parameters:
5419c0446d6SStefano Zampini +  pc - the preconditioning context
542da1bb401SStefano Zampini -  n - number of index sets defining the fields
543da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5449c0446d6SStefano Zampini 
5459c0446d6SStefano Zampini    Level: intermediate
5469c0446d6SStefano Zampini 
5479c0446d6SStefano Zampini    Notes:
5489c0446d6SStefano Zampini 
5499c0446d6SStefano Zampini .seealso: PCBDDC
5509c0446d6SStefano Zampini @*/
5519c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5529c0446d6SStefano Zampini {
5539c0446d6SStefano Zampini   PetscErrorCode ierr;
5549c0446d6SStefano Zampini 
5559c0446d6SStefano Zampini   PetscFunctionBegin;
5569c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5579c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5589c0446d6SStefano Zampini   PetscFunctionReturn(0);
5599c0446d6SStefano Zampini }
560da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
561534831adSStefano Zampini #undef __FUNCT__
562534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
563534831adSStefano Zampini /* -------------------------------------------------------------------------- */
564534831adSStefano Zampini /*
565534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
566534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5679c0446d6SStefano Zampini 
568534831adSStefano Zampini    Input Parameter:
569534831adSStefano Zampini +  pc - the preconditioner contex
570534831adSStefano Zampini 
571534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
572534831adSStefano Zampini 
573534831adSStefano Zampini    Notes:
574534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
575534831adSStefano Zampini    the user, but instead is called by KSPSolve().
576534831adSStefano Zampini */
577534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
578534831adSStefano Zampini {
579534831adSStefano Zampini   PetscErrorCode ierr;
580534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
581534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
582534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
583534831adSStefano Zampini   Mat            temp_mat;
5843972b0daSStefano Zampini   IS             dirIS;
5853972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5863972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5873972b0daSStefano Zampini   Vec            used_vec;
5883972b0daSStefano Zampini   PetscBool      guess_nonzero;
589534831adSStefano Zampini 
590534831adSStefano Zampini   PetscFunctionBegin;
5913972b0daSStefano Zampini   if (x) {
5923972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
5933972b0daSStefano Zampini     used_vec = x;
5943972b0daSStefano Zampini   } else {
5953972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
5963972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
5973972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
5983972b0daSStefano Zampini   }
5993972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6003972b0daSStefano Zampini   if (ksp) {
6013972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6023972b0daSStefano Zampini     if ( !guess_nonzero ) {
6033972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6043972b0daSStefano Zampini     }
6053972b0daSStefano Zampini   }
6063972b0daSStefano Zampini   /* store the original rhs */
6073972b0daSStefano Zampini   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6083972b0daSStefano Zampini 
6093972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
6103972b0daSStefano Zampini   ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6113972b0daSStefano Zampini   ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6123972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6133972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6143972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6153972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6163972b0daSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6173972b0daSStefano Zampini   if (dirIS) {
6183972b0daSStefano Zampini     ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6193972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6203972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6213972b0daSStefano Zampini     ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6222fa5cd67SKarl Rupp     for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6233972b0daSStefano Zampini     ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6243972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6253972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6263972b0daSStefano Zampini   }
6273972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6283972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
629b76ba322SStefano Zampini 
6303972b0daSStefano Zampini   /* remove the computed solution from the rhs */
6313972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6323972b0daSStefano Zampini   ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6333972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
634b76ba322SStefano Zampini 
635b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6363972b0daSStefano Zampini   if (x) {
6373972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6383972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
639b76ba322SStefano Zampini     if (pcbddc->use_exact_dirichlet) {
640b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
641b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
642b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
643b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
644b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
645b76ba322SStefano Zampini       if (ksp) {
646b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
647b76ba322SStefano Zampini       }
648b76ba322SStefano Zampini     }
6493972b0daSStefano Zampini   }
650b76ba322SStefano Zampini 
651b76ba322SStefano Zampini   /* rhs change of basis */
652674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
653b76ba322SStefano Zampini     /* swap pointers for local matrices */
654b76ba322SStefano Zampini     temp_mat = matis->A;
655b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
656b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
657b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
658b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
659b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
660b76ba322SStefano Zampini     /* from original basis to modified basis */
661b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
662b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
663b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
664b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
665674ae819SStefano Zampini   }
6660bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
6670298fd71SBarry Smith     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec,NULL);CHKERRQ(ierr);
6680298fd71SBarry Smith     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs,NULL);CHKERRQ(ierr);
669b76ba322SStefano Zampini   }
6700bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
671534831adSStefano Zampini   PetscFunctionReturn(0);
672534831adSStefano Zampini }
673534831adSStefano Zampini /* -------------------------------------------------------------------------- */
674534831adSStefano Zampini #undef __FUNCT__
675534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
676534831adSStefano Zampini /* -------------------------------------------------------------------------- */
677534831adSStefano Zampini /*
678534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
679534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
680534831adSStefano Zampini 
681534831adSStefano Zampini    Input Parameter:
682534831adSStefano Zampini +  pc - the preconditioner contex
683534831adSStefano Zampini 
684534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
685534831adSStefano Zampini 
686534831adSStefano Zampini    Notes:
687534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
688534831adSStefano Zampini    the user, but instead is called by KSPSolve().
689534831adSStefano Zampini */
690534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
691534831adSStefano Zampini {
692534831adSStefano Zampini   PetscErrorCode ierr;
693534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
694534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
695534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
696534831adSStefano Zampini   Mat            temp_mat;
697534831adSStefano Zampini 
698534831adSStefano Zampini   PetscFunctionBegin;
699674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
700534831adSStefano Zampini     /* swap pointers for local matrices */
701534831adSStefano Zampini     temp_mat = matis->A;
702534831adSStefano Zampini     matis->A = pcbddc->local_mat;
703534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
704534831adSStefano Zampini     /* restore rhs to its original state */
7053425bc38SStefano Zampini     if (rhs) {
7063425bc38SStefano Zampini       ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
7073425bc38SStefano Zampini     }
708534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
709534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
710534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
711534831adSStefano Zampini     /* from modified basis to original basis */
712534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
713534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
714534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
715534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
716534831adSStefano Zampini   }
7173972b0daSStefano Zampini   /* add solution removed in presolve */
7183425bc38SStefano Zampini   if (x) {
7193425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7203425bc38SStefano Zampini   }
721534831adSStefano Zampini   PetscFunctionReturn(0);
722534831adSStefano Zampini }
723534831adSStefano Zampini /* -------------------------------------------------------------------------- */
72453cdbc3dSStefano Zampini #undef __FUNCT__
72553cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7260c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7270c7d97c5SJed Brown /*
7280c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7290c7d97c5SJed Brown                   by setting data structures and options.
7300c7d97c5SJed Brown 
7310c7d97c5SJed Brown    Input Parameter:
73253cdbc3dSStefano Zampini +  pc - the preconditioner context
7330c7d97c5SJed Brown 
7340c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7350c7d97c5SJed Brown 
7360c7d97c5SJed Brown    Notes:
7370c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7380c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7390c7d97c5SJed Brown */
74053cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7410c7d97c5SJed Brown {
7420c7d97c5SJed Brown   PetscErrorCode ierr;
7430c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
744674ae819SStefano Zampini   MatStructure   flag;
745674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7460c7d97c5SJed Brown 
7470c7d97c5SJed Brown   PetscFunctionBegin;
748674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7493b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7509c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7510c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7520c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7530c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7543b03a366Sstefano_zampini   /* Get stdout for dbg */
755674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
756ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
757e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
758e269702eSStefano Zampini   }
759674ae819SStefano Zampini   /* first attempt to split work */
760674ae819SStefano Zampini   if (pc->setupcalled) {
761674ae819SStefano Zampini     computeis = PETSC_FALSE;
762674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
763674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
764674ae819SStefano Zampini       computetopography = PETSC_FALSE;
765674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
766674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
767674ae819SStefano Zampini       computetopography = PETSC_FALSE;
768674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
769674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
770674ae819SStefano Zampini       computetopography = PETSC_TRUE;
771674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
772674ae819SStefano Zampini     }
773674ae819SStefano Zampini   } else {
774674ae819SStefano Zampini     computeis = PETSC_TRUE;
775674ae819SStefano Zampini     computetopography = PETSC_TRUE;
776674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
777674ae819SStefano Zampini   }
778674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
779674ae819SStefano Zampini   if (computeis) {
780674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
781674ae819SStefano Zampini   }
782674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
783674ae819SStefano Zampini   if (computetopography) {
784674ae819SStefano Zampini     /* reset data */
785674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
786674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
787674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
788674ae819SStefano Zampini   }
789674ae819SStefano Zampini   if (computesolvers) {
790674ae819SStefano Zampini     /* reset data */
791674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
792674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
7930c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
7940c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
795674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
7960c7d97c5SJed Brown   }
7970c7d97c5SJed Brown   PetscFunctionReturn(0);
7980c7d97c5SJed Brown }
7990c7d97c5SJed Brown 
8000c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8010c7d97c5SJed Brown /*
8020c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8030c7d97c5SJed Brown 
8040c7d97c5SJed Brown    Input Parameters:
8050c7d97c5SJed Brown .  pc - the preconditioner context
8060c7d97c5SJed Brown .  r - input vector (global)
8070c7d97c5SJed Brown 
8080c7d97c5SJed Brown    Output Parameter:
8090c7d97c5SJed Brown .  z - output vector (global)
8100c7d97c5SJed Brown 
8110c7d97c5SJed Brown    Application Interface Routine: PCApply()
8120c7d97c5SJed Brown  */
8130c7d97c5SJed Brown #undef __FUNCT__
8140c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
81553cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8160c7d97c5SJed Brown {
8170c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8180c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8190c7d97c5SJed Brown   PetscErrorCode    ierr;
8203b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8213b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8222617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8230c7d97c5SJed Brown 
8240c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8250c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
82629622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8270c7d97c5SJed Brown 
8280c7d97c5SJed Brown   PetscFunctionBegin;
829b76ba322SStefano Zampini   if (!pcbddc->use_exact_dirichlet) {
8300c7d97c5SJed Brown     /* First Dirichlet solve */
8310c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8320c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
83353cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8340c7d97c5SJed Brown     /*
8350c7d97c5SJed Brown       Assembling right hand side for BDDC operator
836674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
837674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8380c7d97c5SJed Brown     */
8390c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8400c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
84129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8420c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8430c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8440c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8450c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
846674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
847b76ba322SStefano Zampini   } else {
8480bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
849b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
850674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
851b76ba322SStefano Zampini   }
852b76ba322SStefano Zampini 
8532617d88aSStefano Zampini   /* Apply interface preconditioner
8542617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8552617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8562617d88aSStefano Zampini 
857674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
858674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8590c7d97c5SJed Brown 
8603b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8610c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8620c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8630c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
86429622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
86553cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8660c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
86729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8680c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8690c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8700c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8710c7d97c5SJed Brown   PetscFunctionReturn(0);
8720c7d97c5SJed Brown }
873da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
874674ae819SStefano Zampini 
875da1bb401SStefano Zampini #undef __FUNCT__
876da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
877da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
878da1bb401SStefano Zampini {
879da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
880da1bb401SStefano Zampini   PetscErrorCode ierr;
881da1bb401SStefano Zampini 
882da1bb401SStefano Zampini   PetscFunctionBegin;
883da1bb401SStefano Zampini   /* free data created by PCIS */
884da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
885674ae819SStefano Zampini   /* free BDDC custom data  */
886674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
887674ae819SStefano Zampini   /* destroy objects related to topography */
888674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
889674ae819SStefano Zampini   /* free allocated graph structure */
890da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
891674ae819SStefano Zampini   /* free data for scaling operator */
892674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
893674ae819SStefano Zampini   /* free solvers stuff */
894674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
8953425bc38SStefano Zampini   /* remove functions */
896674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
897bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
898bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
899bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
900bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
901bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
902bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
903bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
904bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
905bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
906bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
907bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
908bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
909bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
910674ae819SStefano Zampini   /* Free the private data structure */
911674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
912da1bb401SStefano Zampini   PetscFunctionReturn(0);
913da1bb401SStefano Zampini }
9143425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9151e6b0712SBarry Smith 
9163425bc38SStefano Zampini #undef __FUNCT__
9173425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9183425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9193425bc38SStefano Zampini {
920674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9213425bc38SStefano Zampini   PC_IS*         pcis;
9223425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9233425bc38SStefano Zampini   PetscErrorCode ierr;
9240c7d97c5SJed Brown 
9253425bc38SStefano Zampini   PetscFunctionBegin;
9263425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9273425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9283425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9293425bc38SStefano Zampini 
9303425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9313425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
9320298fd71SBarry Smith   (*mat_ctx->pc->ops->presolve)(mat_ctx->pc,NULL,standard_rhs,NULL);
9333425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9343425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9353425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
936674ae819SStefano Zampini   /* scale rhs since it should be unassembled : TODO use counter scaling? (also below) */
9373425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9383425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
939674ae819SStefano Zampini   /* Apply partition of unity */
9403425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
941674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
94229622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9433425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9443425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9453425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9463425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9473425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9483425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9493425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
950674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9513425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9523425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9533425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9543425bc38SStefano Zampini   }
9553425bc38SStefano Zampini   /* BDDC rhs */
9563425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
95729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9583425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9593425bc38SStefano Zampini   }
9603425bc38SStefano Zampini   /* apply BDDC */
9613425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9623425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9633425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9643425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9653425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9663425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9673425bc38SStefano Zampini   /* restore original rhs */
9683425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9693425bc38SStefano Zampini   PetscFunctionReturn(0);
9703425bc38SStefano Zampini }
9711e6b0712SBarry Smith 
9723425bc38SStefano Zampini #undef __FUNCT__
9733425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9743425bc38SStefano Zampini /*@
9753425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9763425bc38SStefano Zampini 
9773425bc38SStefano Zampini    Collective
9783425bc38SStefano Zampini 
9793425bc38SStefano Zampini    Input Parameters:
9803425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
9813425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
9823425bc38SStefano Zampini 
9833425bc38SStefano Zampini    Output Parameters:
9843425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
9853425bc38SStefano Zampini 
9863425bc38SStefano Zampini    Level: developer
9873425bc38SStefano Zampini 
9883425bc38SStefano Zampini    Notes:
9893425bc38SStefano Zampini 
9903425bc38SStefano Zampini .seealso: PCBDDC
9913425bc38SStefano Zampini @*/
9923425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9933425bc38SStefano Zampini {
994674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9953425bc38SStefano Zampini   PetscErrorCode ierr;
9963425bc38SStefano Zampini 
9973425bc38SStefano Zampini   PetscFunctionBegin;
9983425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9993425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10003425bc38SStefano Zampini   PetscFunctionReturn(0);
10013425bc38SStefano Zampini }
10023425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10031e6b0712SBarry Smith 
10043425bc38SStefano Zampini #undef __FUNCT__
10053425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10063425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10073425bc38SStefano Zampini {
1008674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10093425bc38SStefano Zampini   PC_IS*         pcis;
10103425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10113425bc38SStefano Zampini   PetscErrorCode ierr;
10123425bc38SStefano Zampini 
10133425bc38SStefano Zampini   PetscFunctionBegin;
10143425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10153425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10163425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10173425bc38SStefano Zampini 
10183425bc38SStefano Zampini   /* apply B_delta^T */
10193425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10203425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10213425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10223425bc38SStefano Zampini   /* compute rhs for BDDC application */
10233425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
102429622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10253425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10263425bc38SStefano Zampini   }
10273425bc38SStefano Zampini   /* apply BDDC */
10283425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10293425bc38SStefano Zampini   /* put values into standard global vector */
10303425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10313425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
103229622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10333425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10343425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10353425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10363425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10373425bc38SStefano Zampini   }
10383425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10393425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10403425bc38SStefano Zampini   /* final change of basis if needed
10413425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10420298fd71SBarry Smith   (*mat_ctx->pc->ops->postsolve)(mat_ctx->pc,NULL,NULL,standard_sol);
10433425bc38SStefano Zampini   PetscFunctionReturn(0);
10443425bc38SStefano Zampini 
10453425bc38SStefano Zampini }
10461e6b0712SBarry Smith 
10473425bc38SStefano Zampini #undef __FUNCT__
10483425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10493425bc38SStefano Zampini /*@
10503425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10513425bc38SStefano Zampini 
10523425bc38SStefano Zampini    Collective
10533425bc38SStefano Zampini 
10543425bc38SStefano Zampini    Input Parameters:
10553425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10563425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10573425bc38SStefano Zampini 
10583425bc38SStefano Zampini    Output Parameters:
10593425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10603425bc38SStefano Zampini 
10613425bc38SStefano Zampini    Level: developer
10623425bc38SStefano Zampini 
10633425bc38SStefano Zampini    Notes:
10643425bc38SStefano Zampini 
10653425bc38SStefano Zampini .seealso: PCBDDC
10663425bc38SStefano Zampini @*/
10673425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10683425bc38SStefano Zampini {
1069674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10703425bc38SStefano Zampini   PetscErrorCode ierr;
10713425bc38SStefano Zampini 
10723425bc38SStefano Zampini   PetscFunctionBegin;
10733425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10743425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10753425bc38SStefano Zampini   PetscFunctionReturn(0);
10763425bc38SStefano Zampini }
10773425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10781e6b0712SBarry Smith 
1079f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1080f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1081f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1082f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1083674ae819SStefano Zampini 
10843425bc38SStefano Zampini #undef __FUNCT__
10853425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
10863425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
10873425bc38SStefano Zampini {
1088674ae819SStefano Zampini 
1089674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
10903425bc38SStefano Zampini   Mat            newmat;
1091674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
10923425bc38SStefano Zampini   PC             newpc;
1093ce94432eSBarry Smith   MPI_Comm       comm;
10943425bc38SStefano Zampini   PetscErrorCode ierr;
10953425bc38SStefano Zampini 
10963425bc38SStefano Zampini   PetscFunctionBegin;
1097ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
10983425bc38SStefano Zampini   /* FETIDP linear matrix */
10993425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11003425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11013425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11023425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11033425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11043425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11053425bc38SStefano Zampini   /* FETIDP preconditioner */
11063425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11073425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11083425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11093425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11103425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11113425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11123425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11133425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11143425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11153425bc38SStefano Zampini   /* return pointers for objects created */
11163425bc38SStefano Zampini   *fetidp_mat=newmat;
11173425bc38SStefano Zampini   *fetidp_pc=newpc;
11183425bc38SStefano Zampini   PetscFunctionReturn(0);
11193425bc38SStefano Zampini }
11201e6b0712SBarry Smith 
11213425bc38SStefano Zampini #undef __FUNCT__
11223425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11233425bc38SStefano Zampini /*@
11243425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11253425bc38SStefano Zampini 
11263425bc38SStefano Zampini    Collective
11273425bc38SStefano Zampini 
11283425bc38SStefano Zampini    Input Parameters:
11293425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11303425bc38SStefano Zampini 
11313425bc38SStefano Zampini    Level: developer
11323425bc38SStefano Zampini 
11333425bc38SStefano Zampini    Notes:
11343425bc38SStefano Zampini 
11353425bc38SStefano Zampini .seealso: PCBDDC
11363425bc38SStefano Zampini @*/
11373425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11383425bc38SStefano Zampini {
11393425bc38SStefano Zampini   PetscErrorCode ierr;
11403425bc38SStefano Zampini 
11413425bc38SStefano Zampini   PetscFunctionBegin;
11423425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11433425bc38SStefano Zampini   if (pc->setupcalled) {
11443425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1145f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11463425bc38SStefano Zampini   PetscFunctionReturn(0);
11473425bc38SStefano Zampini }
11480c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1149da1bb401SStefano Zampini /*MC
1150da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11510c7d97c5SJed Brown 
1152da1bb401SStefano Zampini    Options Database Keys:
1153da1bb401SStefano Zampini .    -pcbddc ??? -
1154da1bb401SStefano Zampini 
1155da1bb401SStefano Zampini    Level: intermediate
1156da1bb401SStefano Zampini 
1157da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1158da1bb401SStefano Zampini 
1159da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1160da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1161da1bb401SStefano Zampini           on the subdomains).
1162da1bb401SStefano Zampini 
1163da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1164da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1165da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1166da1bb401SStefano Zampini 
1167da1bb401SStefano Zampini    Contributed by Stefano Zampini
1168da1bb401SStefano Zampini 
1169da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1170da1bb401SStefano Zampini M*/
1171b2573a8aSBarry Smith 
1172da1bb401SStefano Zampini #undef __FUNCT__
1173da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11748cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1175da1bb401SStefano Zampini {
1176da1bb401SStefano Zampini   PetscErrorCode      ierr;
1177da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1178da1bb401SStefano Zampini 
1179da1bb401SStefano Zampini   PetscFunctionBegin;
1180da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1181da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1182da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1183da1bb401SStefano Zampini 
1184da1bb401SStefano Zampini   /* create PCIS data structure */
1185da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1186da1bb401SStefano Zampini 
1187da1bb401SStefano Zampini   /* BDDC specific */
1188674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
11890bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
11903972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1191534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1192534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1193534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1194674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1195674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1196da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1197da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1198da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1199da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1200da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
1201da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1202da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1203da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1204da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1205da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1206da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1207da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1208da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1209da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1210da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
121129622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1212da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1213da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1214da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1215da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1216da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1217da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1218da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
1219*9d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1220da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1221b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12224fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12234fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1224674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1225674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1226da1bb401SStefano Zampini 
1227674ae819SStefano Zampini   /* create local graph structure */
1228674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1229674ae819SStefano Zampini 
1230674ae819SStefano Zampini   /* scaling */
1231674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1232674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1233da1bb401SStefano Zampini 
1234da1bb401SStefano Zampini   /* function pointers */
1235da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1236da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1237da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1238da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1239da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1240da1bb401SStefano Zampini   pc->ops->view                = 0;
1241da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1242da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1243da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1244534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1245534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1246da1bb401SStefano Zampini 
1247da1bb401SStefano Zampini   /* composing function */
1248674ae819SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1249bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1250bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1251bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1252bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1253bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1254bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1255bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1256bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1257bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1258bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1259bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1260bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1261bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1262da1bb401SStefano Zampini   PetscFunctionReturn(0);
1263da1bb401SStefano Zampini }
12643425bc38SStefano Zampini 
1265da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1266da1bb401SStefano Zampini /* All static functions from now on                                           */
1267da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
126829622bf0SStefano Zampini 
126929622bf0SStefano Zampini #undef __FUNCT__
12702e8d2280SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
12712e8d2280SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool use)
12722e8d2280SStefano Zampini {
12732e8d2280SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12742e8d2280SStefano Zampini 
12752e8d2280SStefano Zampini   PetscFunctionBegin;
12762e8d2280SStefano Zampini   pcbddc->use_exact_dirichlet=use;
12772e8d2280SStefano Zampini   PetscFunctionReturn(0);
12782e8d2280SStefano Zampini }
12792e8d2280SStefano Zampini 
12802e8d2280SStefano Zampini #undef __FUNCT__
12814fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12824fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12834fad6a16SStefano Zampini {
12844fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12854fad6a16SStefano Zampini 
12864fad6a16SStefano Zampini   PetscFunctionBegin;
12874fad6a16SStefano Zampini   pcbddc->current_level=level;
12884fad6a16SStefano Zampini   PetscFunctionReturn(0);
12894fad6a16SStefano Zampini }
12903425bc38SStefano Zampini 
12913b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
12920c7d97c5SJed Brown #undef __FUNCT__
12930c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
129453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
12950c7d97c5SJed Brown {
12960c7d97c5SJed Brown   PetscErrorCode  ierr;
1297674ae819SStefano Zampini 
12980c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
12990c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
13000c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1301534831adSStefano Zampini   Mat               change_mat_all;
13020c7d97c5SJed Brown   IS                is_R_local;
13030c7d97c5SJed Brown   IS                is_V_local;
13040c7d97c5SJed Brown   IS                is_C_local;
13050c7d97c5SJed Brown   IS                is_aux1;
13060c7d97c5SJed Brown   IS                is_aux2;
130719fd82e9SBarry Smith   VecType           impVecType;
130819fd82e9SBarry Smith   MatType           impMatType;
13090c7d97c5SJed Brown   PetscInt          n_R=0;
13100c7d97c5SJed Brown   PetscInt          n_D=0;
13110c7d97c5SJed Brown   PetscInt          n_B=0;
13120c7d97c5SJed Brown   PetscScalar       zero=0.0;
13130c7d97c5SJed Brown   PetscScalar       one=1.0;
13140c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
13150c7d97c5SJed Brown   PetscScalar*      array;
13160c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
13170c7d97c5SJed Brown   PetscInt          *idx_R_local;
13180c7d97c5SJed Brown   PetscInt          *idx_V_B;
13190c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
13200c7d97c5SJed Brown   PetscScalar       *constraints_errors;
13210c7d97c5SJed Brown   /* auxiliary indices */
1322534831adSStefano Zampini   PetscInt          i,j,k;
1323e269702eSStefano Zampini   /* for verbose output of bddc */
1324e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1325e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1326a0ba757dSStefano Zampini   /* for counting coarse dofs */
1327534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
13283b03a366Sstefano_zampini   PetscInt          size_of_constraint;
13293b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
13303b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1331534831adSStefano Zampini   PetscInt          *vertices,*nnz,*is_indices,*temp_indices;
1332674ae819SStefano Zampini   ISLocalToGlobalMapping BtoNmap;
13330c7d97c5SJed Brown 
13340c7d97c5SJed Brown   PetscFunctionBegin;
13350c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
13360c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
1337534831adSStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
1338534831adSStefano Zampini   impMatType = MATSEQDENSE;
1339534831adSStefano Zampini   impVecType = VECSEQ;
1340da1bb401SStefano Zampini   /* get vertex indices from constraint matrix */
1341674ae819SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1342534831adSStefano Zampini   /* Set number of constraints */
1343534831adSStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
1344534831adSStefano Zampini 
1345534831adSStefano Zampini   /* vertices in boundary numbering */
1346534831adSStefano Zampini   ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1347674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
1348674ae819SStefano Zampini   ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
1349674ae819SStefano Zampini   if (i != n_vertices) {
1350674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1351534831adSStefano Zampini   }
1352534831adSStefano Zampini 
1353534831adSStefano Zampini   /* transform local matrices if needed */
1354674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
1355534831adSStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1356534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13572fa5cd67SKarl Rupp     for (i=0;i<n_D;i++) nnz[is_indices[i]] = 1;
1358534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1359534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1360534831adSStefano Zampini     k=1;
1361534831adSStefano Zampini     for (i=0;i<n_B;i++) {
13620298fd71SBarry Smith       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1363534831adSStefano Zampini       nnz[is_indices[i]]=j;
13642fa5cd67SKarl Rupp       if (k < j) k = j;
13650298fd71SBarry Smith       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1366534831adSStefano Zampini     }
1367534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1368534831adSStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
1369534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
1370534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
1371534831adSStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
1372534831adSStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
1373534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
1374534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1375534831adSStefano Zampini     for (i=0;i<n_D;i++) {
1376534831adSStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
1377534831adSStefano Zampini     }
1378534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1379534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1380534831adSStefano Zampini     for (i=0;i<n_B;i++) {
1381534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
13822fa5cd67SKarl Rupp       for (k=0; k<j; k++) temp_indices[k]=is_indices[row_cmat_indices[k]];
1383534831adSStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
1384534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
1385534831adSStefano Zampini     }
1386534831adSStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1387534831adSStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13885ce978abSStefano Zampini     /* TODO: HOW TO WORK WITH BAIJ? PtAP not provided */
13895ce978abSStefano Zampini     ierr = MatGetBlockSize(matis->A,&i);CHKERRQ(ierr);
13905ce978abSStefano Zampini     if (i==1) {
1391534831adSStefano Zampini       ierr = MatPtAP(matis->A,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13925ce978abSStefano Zampini     } else {
13935ce978abSStefano Zampini       Mat work_mat;
13945ce978abSStefano Zampini       ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
13955ce978abSStefano Zampini       ierr = MatPtAP(work_mat,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13965ce978abSStefano Zampini       ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
13975ce978abSStefano Zampini     }
1398534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
1399534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
1400534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
1401534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
1402534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
1403534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
1404534831adSStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
1405534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1406534831adSStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
1407534831adSStefano Zampini   } else {
1408534831adSStefano Zampini     /* without change of basis, the local matrix is unchanged */
1409534831adSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1410534831adSStefano Zampini     pcbddc->local_mat = matis->A;
1411534831adSStefano Zampini   }
1412674ae819SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1413674ae819SStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1414674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
14150bdf917eSStefano Zampini   }
1416a0ba757dSStefano Zampini 
14170c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
14180c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
14190c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14202fa5cd67SKarl Rupp   for (i=0;i<n_vertices;i++) array[vertices[i]] = zero;
14213b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
14222fa5cd67SKarl Rupp   for (i=0, n_R=0; i<pcis->n; i++) {
14232fa5cd67SKarl Rupp     if (array[i] == one) {
14242fa5cd67SKarl Rupp       idx_R_local[n_R] = i;
14252fa5cd67SKarl Rupp       n_R++;
14262fa5cd67SKarl Rupp     }
14272fa5cd67SKarl Rupp   }
14280c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1429e269702eSStefano Zampini   if (dbg_flag) {
14300c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14310c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14320c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
14330c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
14343b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr);
1435534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
14360c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14370c7d97c5SJed Brown   }
1438534831adSStefano Zampini 
14390c7d97c5SJed Brown   /* Allocate needed vectors */
1440534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
14413972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
14420c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
14430c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
14440c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
14450c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1446d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
14470c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
14480c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
14490c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
14500c7d97c5SJed Brown 
14510c7d97c5SJed Brown   /* Creating some index sets needed  */
14520c7d97c5SJed Brown   /* For submatrices */
1453da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
14543b03a366Sstefano_zampini   if (n_vertices)    {
1455da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_OWN_POINTER,&is_V_local);CHKERRQ(ierr);
14563b03a366Sstefano_zampini   }
1457da1bb401SStefano Zampini   if (n_constraints) {
1458da1bb401SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
1459da1bb401SStefano Zampini   }
1460da1bb401SStefano Zampini 
14610c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
14620c7d97c5SJed Brown   {
14630c7d97c5SJed Brown     PetscInt   *aux_array1;
14640c7d97c5SJed Brown     PetscInt   *aux_array2;
14652e8d2280SStefano Zampini     PetscInt   *idx_I_local;
14660c7d97c5SJed Brown 
14673b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14683b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
14690c7d97c5SJed Brown 
14702e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14710c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14722fa5cd67SKarl Rupp     for (i=0; i<n_D; i++) array[idx_I_local[i]] = 0;
14732e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14742fa5cd67SKarl Rupp     for (i=0, j=0; i<n_R; i++) {
14752fa5cd67SKarl Rupp       if (array[idx_R_local[i]] == one) {
14762fa5cd67SKarl Rupp         aux_array1[j] = i;
14772fa5cd67SKarl Rupp         j++;
14782fa5cd67SKarl Rupp       }
14792fa5cd67SKarl Rupp     }
14800c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1481da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
14822e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14832e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14840c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
14852fa5cd67SKarl Rupp     for (i=0, j=0; i<n_B; i++) {
14862fa5cd67SKarl Rupp       if (array[i] == one) {
14872fa5cd67SKarl Rupp         aux_array2[j] = i; j++;
14882fa5cd67SKarl Rupp       }
14892fa5cd67SKarl Rupp     }
14903828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1491da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
14920c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
14930c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
14940c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
14950c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14960c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
14970c7d97c5SJed Brown 
149829622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
14990c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
15000c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15012fa5cd67SKarl Rupp       for (i=0, j=0; i<n_R; i++) {
15022fa5cd67SKarl Rupp         if (array[idx_R_local[i]] == zero) {
15032fa5cd67SKarl Rupp           aux_array1[j] = i;
15042fa5cd67SKarl Rupp           j++;
15052fa5cd67SKarl Rupp         }
15062fa5cd67SKarl Rupp       }
15070c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1508da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
15090c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
15100c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
15110c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
15120c7d97c5SJed Brown     }
15130c7d97c5SJed Brown   }
15140c7d97c5SJed Brown 
15150c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
15160c7d97c5SJed Brown   {
15170c7d97c5SJed Brown     Mat          A_RR;
151853cdbc3dSStefano Zampini     PC           pc_temp;
1519674ae819SStefano Zampini     MatStructure matstruct;
1520674ae819SStefano Zampini     /* Matrix for Dirichlet problem is A_II */
1521674ae819SStefano Zampini     /* HACK (TODO) A_II can be changed between nonlinear iterations */
1522674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&matstruct);CHKERRQ(ierr);
1523674ae819SStefano Zampini     if (matstruct == SAME_NONZERO_PATTERN) {
1524674ae819SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_I_local,MAT_REUSE_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1525674ae819SStefano Zampini     } else {
1526674ae819SStefano Zampini       ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
1527674ae819SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1528674ae819SStefano Zampini     }
152953cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
153053cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
153153cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
153253cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1533da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
15340c7d97c5SJed Brown     /* default */
153553cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
153653cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
15370c7d97c5SJed Brown     /* Allow user's customization */
153853cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1539950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
1540950d796eSStefano Zampini     if (!n_D) {
15412e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1542950d796eSStefano Zampini     }
154353cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
154453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
15453972b0daSStefano Zampini     /* set ksp_D into pcis data */
15463972b0daSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
15473972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
15483972b0daSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
15490c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
1550534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
155153cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
155253cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
155353cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
155453cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1555da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
15560c7d97c5SJed Brown     /* default */
155753cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
155853cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
15590c7d97c5SJed Brown     /* Allow user's customization */
156053cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1561950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
1562674ae819SStefano Zampini     if (!n_R) {
15632e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1564950d796eSStefano Zampini     }
156553cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
156653cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1567674ae819SStefano Zampini     /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
1568b76ba322SStefano Zampini     {
15690c7d97c5SJed Brown       Vec         temp_vec;
1570b76ba322SStefano Zampini       PetscReal   value;
1571b76ba322SStefano Zampini       PetscMPIInt use_exact,use_exact_reduced;
15720c7d97c5SJed Brown 
1573a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
15740298fd71SBarry Smith       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
1575a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1576a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1577a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1578a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
157929622bf0SStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1580b76ba322SStefano Zampini       use_exact = 1;
15812fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1582ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1583b76ba322SStefano Zampini       pcbddc->use_exact_dirichlet = (PetscBool) use_exact_reduced;
1584b76ba322SStefano Zampini       if (dbg_flag) {
1585a0ba757dSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1586a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1587a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1588a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1589674ae819SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
159029622bf0SStefano Zampini       }
1591674ae819SStefano Zampini       if (n_D && pcbddc->NullSpace && !use_exact_reduced && !pcbddc->inexact_prec_type) {
1592674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);
159329622bf0SStefano Zampini       }
1594d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
15950298fd71SBarry Smith       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
1596d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1597d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1598d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1599d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1600e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
160129622bf0SStefano Zampini       use_exact = 1;
16022fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1603ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
160429622bf0SStefano Zampini       if (dbg_flag) {
16050c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1606d49ef151SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
16070c7d97c5SJed Brown       }
1608674ae819SStefano Zampini       if (n_R && pcbddc->NullSpace && !use_exact_reduced) {
1609674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,is_R_local);
161029622bf0SStefano Zampini       }
1611b76ba322SStefano Zampini     }
16120c7d97c5SJed Brown     /* free Neumann problem's matrix */
16130c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
16140c7d97c5SJed Brown   }
16150c7d97c5SJed Brown 
16160c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
16170c7d97c5SJed Brown   {
16180c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
16190bdf917eSStefano Zampini     Mat          M1;
16200c7d97c5SJed Brown     Mat          C_CR;
16213b03a366Sstefano_zampini     Mat          AUXMAT;
16220c7d97c5SJed Brown     Vec          vec1_C;
16230c7d97c5SJed Brown     Vec          vec2_C;
16240c7d97c5SJed Brown     Vec          vec1_V;
16250c7d97c5SJed Brown     Vec          vec2_V;
16260c7d97c5SJed Brown     PetscInt     *nnz;
16270c7d97c5SJed Brown     PetscInt     *auxindices;
162853cdbc3dSStefano Zampini     PetscInt     index;
16290c7d97c5SJed Brown     PetscScalar* array2;
16300c7d97c5SJed Brown     MatFactorInfo matinfo;
16310c7d97c5SJed Brown 
16320c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
16330c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
16340c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
16352fa5cd67SKarl Rupp     for (i=0;i<pcis->n;i++) auxindices[i]=i;
16360c7d97c5SJed Brown 
16370c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
16383b03a366Sstefano_zampini     if (n_vertices) {
16390c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
16403b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
16410c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
16420c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
16430c7d97c5SJed Brown     }
1644534831adSStefano Zampini     if (n_constraints) {
16450c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
1646534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
16470c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
16480c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
16490c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
16500c7d97c5SJed Brown     }
16510c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
16523b03a366Sstefano_zampini     if (n_constraints) {
16530c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
16543b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
16550c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
16560298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,NULL);CHKERRQ(ierr);
16570c7d97c5SJed Brown 
165857a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
165957a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
166057a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
166157a90decSStefano Zampini 
16620c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
16633b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
16643b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
16653b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
166657a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
166757a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
16682fa5cd67SKarl Rupp         for (j=0;j<size_of_constraint;j++) array[row_cmat_indices[j]] = -row_cmat_values[j];
166957a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
167057a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
16712fa5cd67SKarl Rupp 
16723b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
167353cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
16742fa5cd67SKarl Rupp 
16753b03a366Sstefano_zampini         /* Set values */
16760c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
16773b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
16780c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
16790c7d97c5SJed Brown       }
16800c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16810c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16820c7d97c5SJed Brown 
16830c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
16840c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1685d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
16863b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
16870c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
16880c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
16890c7d97c5SJed Brown 
16903b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1691d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
16923b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
16930c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
16940298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(M1,NULL);CHKERRQ(ierr);
16953b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
16960c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
16970c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
16980c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
16990c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
17000c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
17010c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
17020c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
17033b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17040c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
17050c7d97c5SJed Brown       }
17060c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17070c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17080c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
17090c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
17100c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
17110c7d97c5SJed Brown 
17120c7d97c5SJed Brown     }
17130c7d97c5SJed Brown 
17140c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
17153b03a366Sstefano_zampini     if (n_vertices){
1716534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1717534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1718534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
17190c7d97c5SJed Brown     }
17200c7d97c5SJed Brown 
17210c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1722d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
17230c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
17240c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
17250298fd71SBarry Smith     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,NULL);CHKERRQ(ierr);
172629622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
1727d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
17280c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
17290c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
17300298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,NULL);CHKERRQ(ierr);
17310c7d97c5SJed Brown     }
17320c7d97c5SJed Brown 
1733e269702eSStefano Zampini     if (dbg_flag) {
17340c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
17350c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
17360c7d97c5SJed Brown     }
17373b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
17380c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
17390c7d97c5SJed Brown 
17400c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
17413b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++){
17420c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
17430c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
17440c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
17450c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
17460c7d97c5SJed Brown       /* solution of saddle point problem */
17470bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
17480bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17490c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
17503b03a366Sstefano_zampini       if (n_constraints) {
17510c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
17520c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17530c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
17540c7d97c5SJed Brown       }
17550c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
17560c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
17570c7d97c5SJed Brown 
17580c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
17590c7d97c5SJed Brown       /* coarse basis functions */
17600c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
17610c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17620c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17630c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17643b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17650c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17660c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
176729622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag  ) {
17680c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17690c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17700c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17713b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17720c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17730c7d97c5SJed Brown       }
17740c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
17750c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
17762fa5cd67SKarl Rupp       for (j=0; j<n_vertices; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j];   /* WARNING -> column major ordering */
17770c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
17783b03a366Sstefano_zampini       if (n_constraints) {
17790c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
17802fa5cd67SKarl Rupp         for (j=0; j<n_constraints; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j+n_vertices] = array[j];   /* WARNING -> column major ordering */
17810c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
17820c7d97c5SJed Brown       }
17830c7d97c5SJed Brown 
1784e269702eSStefano Zampini       if ( dbg_flag ) {
17850c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1786d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
17870c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
17880c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
17892fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
17903b03a366Sstefano_zampini         array[ vertices[i] ] = one;
17910c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
17920c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
17930c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1794d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
17950c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
17960c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
17972fa5cd67SKarl Rupp         for (j=0;j<n_vertices;j++) array2[j]=array[j];
17980c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
17993b03a366Sstefano_zampini         if (n_constraints) {
18000c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18012fa5cd67SKarl Rupp           for (j=0;j<n_constraints;j++) array2[j+n_vertices]=array[j];
18020c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18030c7d97c5SJed Brown         }
18040c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18050c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
18060c7d97c5SJed Brown         /* check saddle point solution */
1807534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
18083b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
18093b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
18103b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
18110c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18123b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
18130c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18143b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
18150c7d97c5SJed Brown       }
18160c7d97c5SJed Brown     }
18170c7d97c5SJed Brown 
18183b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++){
1819d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
18200c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
18210c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
18220c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
18230c7d97c5SJed Brown       /* solution of saddle point problem */
18240c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
18250c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
18260c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
18273b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
18280c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
18290c7d97c5SJed Brown       /* coarse basis functions */
18303b03a366Sstefano_zampini       index=i+n_vertices;
18310c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
18320c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18330c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18340c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
183553cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18360c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
183729622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
18380c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18390c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18400c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
184153cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18420c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
18430c7d97c5SJed Brown       }
18440c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
18453b03a366Sstefano_zampini       if (n_vertices) {
18460c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18472fa5cd67SKarl Rupp         for (j=0; j<n_vertices; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j]; /* WARNING -> column major ordering */
18480c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18490c7d97c5SJed Brown       }
18500c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18512fa5cd67SKarl Rupp       for (j=0; j<n_constraints; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j+n_vertices]=array[j]; /* WARNING -> column major ordering */
18520c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18530c7d97c5SJed Brown 
1854e269702eSStefano Zampini       if ( dbg_flag ) {
18550c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
185653cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18570c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18580c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18592fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
18600c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18610c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18620c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
186353cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
18640c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18653b03a366Sstefano_zampini         if ( n_vertices) {
18660c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18672fa5cd67SKarl Rupp           for (j=0;j<n_vertices;j++) array2[j]=-array[j];
18680c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18690c7d97c5SJed Brown         }
18700c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18713b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
18720c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18730c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18743972b0daSStefano Zampini         /* check saddle point solution */
1875534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
18763b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
187753cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
18783b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
18790c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
188053cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
18810c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
188253cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
18830c7d97c5SJed Brown       }
18840c7d97c5SJed Brown     }
18850c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18860c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
188729622bf0SStefano Zampini     if ( pcbddc->inexact_prec_type || dbg_flag ) {
18880c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18890c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18900c7d97c5SJed Brown     }
18910c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
18920c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
18939d2fce94SStefano Zampini     if (dbg_flag) {
18940c7d97c5SJed Brown       Mat         coarse_sub_mat;
18950c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
18960c7d97c5SJed Brown       Mat         coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
189719fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
18980c7d97c5SJed Brown       PetscScalar value;
18990c7d97c5SJed Brown 
1900c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1901c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1902c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1903c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1904c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1905c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1906c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1907c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
19080c7d97c5SJed Brown 
19090c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
19100c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
19110c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
191253cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
191353cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
191453cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1915c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
191653cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
191753cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1918c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
191953cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
192053cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
192153cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
192253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
192353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
192453cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
19250c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
19260c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
19270c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
19280c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
192953cdbc3dSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr); }
19300c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
193153cdbc3dSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr); }
19320c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
193353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
193453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
193553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
193653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
193753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
193853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
193953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
194053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
194153cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
194253cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
194353cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
19440c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
19450c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
19460c7d97c5SJed Brown     }
19470c7d97c5SJed Brown     /* free memory */
19483b03a366Sstefano_zampini     if (n_vertices) {
19490c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
19500c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
19510c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
19520c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
19530c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
19540c7d97c5SJed Brown     }
1955534831adSStefano Zampini     if (n_constraints) {
19560c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
19570c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
19580c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
19590c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
19600c7d97c5SJed Brown     }
1961a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
1962a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1963a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
1964674ae819SStefano Zampini     ierr = PCBDDCSetUpCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
1965a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
19660c7d97c5SJed Brown   }
19670c7d97c5SJed Brown   /* free memory */
19683b03a366Sstefano_zampini   if (n_vertices) {
19690c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
19700c7d97c5SJed Brown   }
1971674ae819SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
1972674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
19730c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1974674ae819SStefano Zampini 
19750c7d97c5SJed Brown   PetscFunctionReturn(0);
19760c7d97c5SJed Brown }
19770c7d97c5SJed Brown 
19780c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
19790c7d97c5SJed Brown 
19800c7d97c5SJed Brown #undef __FUNCT__
1981674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
1982674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
19830c7d97c5SJed Brown {
1984674ae819SStefano Zampini 
1985674ae819SStefano Zampini 
19860c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
19870c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
19880c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1989ce94432eSBarry Smith   MPI_Comm  prec_comm;
19900c7d97c5SJed Brown   MPI_Comm  coarse_comm;
19910c7d97c5SJed Brown 
1992674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1993674ae819SStefano Zampini 
19940c7d97c5SJed Brown   /* common to all choiches */
19950c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
19960c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
19970c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
19980c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
19990c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
20000c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
20010c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
20020c7d97c5SJed Brown   PetscMPIInt master_proc=0;
20030c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
20040c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
20050c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
20060c7d97c5SJed Brown   PetscMPIInt count_recv=0;
20070c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
20080c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
20090c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
20100c7d97c5SJed Brown   /* some other variables */
20110c7d97c5SJed Brown   PetscErrorCode ierr;
201219fd82e9SBarry Smith   MatType coarse_mat_type;
201319fd82e9SBarry Smith   PCType  coarse_pc_type;
201419fd82e9SBarry Smith   KSPType coarse_ksp_type;
201553cdbc3dSStefano Zampini   PC pc_temp;
20164fad6a16SStefano Zampini   PetscInt i,j,k;
20173b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
2018e269702eSStefano Zampini   /* verbose output viewer */
2019e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2020e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
2021142dfd88SStefano Zampini 
2022ea7e1babSStefano Zampini   PetscInt      offset,offset2;
2023a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
2024523858cfSStefano Zampini   PetscInt      *dnz,*onz;
2025142dfd88SStefano Zampini 
2026142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
20270c7d97c5SJed Brown 
20280c7d97c5SJed Brown   PetscFunctionBegin;
20294b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
20300c7d97c5SJed Brown   ins_local_primal_indices = 0;
20310c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
20320c7d97c5SJed Brown   localsizes2              = 0;
20330c7d97c5SJed Brown   localdispl2              = 0;
20340c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
20350c7d97c5SJed Brown   coarse_ISLG              = 0;
20360c7d97c5SJed Brown 
203753cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
203853cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
2039142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
2040142dfd88SStefano Zampini 
2041beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
2042beed3852SStefano Zampini   {
2043674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
2044ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
2045ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
2046ef028eecSStefano Zampini 
2047ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
2048beed3852SStefano Zampini 
2049beed3852SStefano Zampini     /* Construct needed data structures for message passing */
2050ffe5efe1SStefano Zampini     j = 0;
2051142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2052ffe5efe1SStefano Zampini       j = size_prec_comm;
2053ffe5efe1SStefano Zampini     }
2054ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
2055ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2056beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
2057142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20585619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
2059ffe5efe1SStefano Zampini     } else {
2060ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
2061ffe5efe1SStefano Zampini     }
2062beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
2063ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
2064beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
2065beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
2066beed3852SStefano Zampini     }
2067beed3852SStefano Zampini 
2068da1bb401SStefano Zampini     /* First let's count coarse dofs.
2069beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
2070beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
2071beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2072ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
2073674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
2074674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
2075674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2076674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
2077674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
2078674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2079ef028eecSStefano Zampini     /* Compute number of coarse dofs */
2080674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
2081ef028eecSStefano Zampini 
2082ef028eecSStefano Zampini     if (dbg_flag) {
20832e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20842e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
20852e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
20862e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
20872e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20882fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
2089beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20902e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2091da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2092da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2093da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2094da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2095da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20962e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
20972e8d2280SStefano Zampini         if (array[i] == 1.0) {
20982e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
20992e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
21002e8d2280SStefano Zampini         }
21012e8d2280SStefano Zampini       }
21022e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21032e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
21042fa5cd67SKarl Rupp         if (array[i] > 0.0) array[i] = 1.0/array[i];
21052e8d2280SStefano Zampini       }
2106da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
21072e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2108da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2109da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2110da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
21112e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
21122e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21132e8d2280SStefano Zampini     }
2114142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
21150bdf917eSStefano Zampini   }
21160bdf917eSStefano Zampini 
21172e8d2280SStefano Zampini   if (dbg_flag) {
21187cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
2119*9d9e44b6SStefano Zampini     if (dbg_flag > 1) {
2120674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
2121674ae819SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2122674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2123674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
2124674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
2125674ae819SStefano Zampini       }
21262e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21272e8d2280SStefano Zampini     }
2128*9d9e44b6SStefano Zampini   }
21292e8d2280SStefano Zampini 
2130a929c220SStefano Zampini   im_active = 0;
21312fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
2132a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
21330bdf917eSStefano Zampini 
21340bdf917eSStefano Zampini   /* adapt coarse problem type */
21354fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
21364fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2137a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
21380bdf917eSStefano Zampini         if (dbg_flag) {
2139a929c220SStefano 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);
21400bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21410bdf917eSStefano Zampini         }
21420bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2143142dfd88SStefano Zampini       }
21444fad6a16SStefano Zampini     } else {
21454fad6a16SStefano Zampini       if (dbg_flag) {
2146a929c220SStefano 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);
21474fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21484fad6a16SStefano Zampini       }
21494fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
21504fad6a16SStefano Zampini     }
21514fad6a16SStefano Zampini   }
2152beed3852SStefano Zampini 
21530c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
21540c7d97c5SJed Brown 
2155da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
21560c7d97c5SJed Brown     {
21570c7d97c5SJed Brown       /* we need additional variables */
21580c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
21590c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
21600c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
21610c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
21620c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
21630c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
21640c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
21650c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
21660c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
21670c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
21680c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
21690c7d97c5SJed Brown       MetisInt    *faces_adjncy;
21700c7d97c5SJed Brown       MetisInt    *faces_xadj;
21710c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
21720c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
21730c7d97c5SJed Brown       PetscInt    *array_int;
21740c7d97c5SJed Brown       PetscMPIInt my_faces=0;
21750c7d97c5SJed Brown       PetscMPIInt total_faces=0;
21763828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
21770c7d97c5SJed Brown 
21780c7d97c5SJed Brown       /* define some quantities */
21790c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
21800c7d97c5SJed Brown       coarse_mat_type = MATIS;
21810c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
2182142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
21830c7d97c5SJed Brown 
21840c7d97c5SJed Brown       /* details of coarse decomposition */
2185a929c220SStefano Zampini       n_subdomains = active_procs;
21860c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2187a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
21883828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
21893828260eSStefano Zampini 
2190a929c220SStefano Zampini #if 0
2191a929c220SStefano Zampini       PetscMPIInt *old_ranks;
2192a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2193a929c220SStefano Zampini       MatPartitioning mat_part;
2194a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2195a929c220SStefano Zampini       PetscViewer viewer_test;
2196a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
2197a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
2198a929c220SStefano Zampini       Mat         mat_adj;
2199a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2200a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2201a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2202a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2203a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2204a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2205a929c220SStefano Zampini       if (im_active) {
2206a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2207a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2208a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2209a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2210a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2211674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2212674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2213a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2214a929c220SStefano Zampini         k = pcis->n_neigh-1;
2215a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2216a929c220SStefano Zampini         ii[0]=0;
2217a929c220SStefano Zampini         ii[1]=k;
2218a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2219674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2220a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
22210298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2222a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2223a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2224a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2225a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2226a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2227a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2228a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2229a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2230a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2231a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2232a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2233a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2234a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2235a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2236a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2237a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2238a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2239a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2240a929c220SStefano Zampini       }
2241a929c220SStefano Zampini #endif
2242a929c220SStefano Zampini 
22434fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
22440c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
22453828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
22460c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
22470c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22480c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
22490c7d97c5SJed Brown         }
22500c7d97c5SJed Brown       }
22510c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
22520c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22537cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
22540c7d97c5SJed Brown             my_faces++;
22550c7d97c5SJed Brown             break;
22560c7d97c5SJed Brown           }
22570c7d97c5SJed Brown         }
22580c7d97c5SJed Brown       }
22590c7d97c5SJed Brown 
226053cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
22610c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
22620c7d97c5SJed Brown       my_faces=0;
22630c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
22640c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22657cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
22660c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
22670c7d97c5SJed Brown             my_faces++;
22680c7d97c5SJed Brown             break;
22690c7d97c5SJed Brown           }
22700c7d97c5SJed Brown         }
22710c7d97c5SJed Brown       }
22720c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22730c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
22740c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
22750c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
22760c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
22770c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
22780c7d97c5SJed Brown       }
227953cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
22800c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22810c7d97c5SJed Brown         faces_xadj[0]=0;
22820c7d97c5SJed Brown         faces_displacements[0]=0;
22830c7d97c5SJed Brown         j=0;
22840c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
22850c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
22860c7d97c5SJed Brown           if (number_of_faces[i-1]) {
22870c7d97c5SJed Brown             j++;
22880c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
22890c7d97c5SJed Brown           }
22900c7d97c5SJed Brown         }
22910c7d97c5SJed Brown       }
229253cdbc3dSStefano 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);
22930c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
22940c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
22950c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22963828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
22970c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
22980c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
22990c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
23000c7d97c5SJed Brown       }
23010c7d97c5SJed Brown 
23020c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
2303674ae819SStefano Zampini 
23043828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
2305674ae819SStefano Zampini 
23060c7d97c5SJed Brown         ncon=1;
23070c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
23080c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
23090c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
23100c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
23110c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
23120c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
23130c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
23144fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
23153828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
23163828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
23173828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
23180c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2319674ae819SStefano 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);
23203828260eSStefano Zampini           } else {
23213828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2322674ae819SStefano 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);
23233828260eSStefano Zampini           }
23244fad6a16SStefano Zampini         } else {
23252fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
23264fad6a16SStefano Zampini         }
23270c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
23280c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
23290bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
23302fa5cd67SKarl Rupp 
23310c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
23322fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
23332fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
23340c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
23350c7d97c5SJed Brown       }
23360c7d97c5SJed Brown 
23370c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
23380c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2339da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2340da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
23410c7d97c5SJed Brown       }
2342da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2343da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
234453cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
23450c7d97c5SJed Brown 
23460c7d97c5SJed Brown       if ( coarse_color == 0 ) {
234753cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
234853cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
23490c7d97c5SJed Brown       } else {
23500c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
23510c7d97c5SJed Brown       }
23520c7d97c5SJed Brown 
23537cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
23540c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
23550c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
23560bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
23570bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
23580c7d97c5SJed Brown         /* some initializations */
23590c7d97c5SJed Brown         displacements_recv[0]=0;
23600bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
23610c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
23620bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
23630bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
23642fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
23650bdf917eSStefano Zampini           }
23660bdf917eSStefano Zampini         }
23670c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
23682fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
23692fa5cd67SKarl Rupp 
23700c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
23710c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
23720c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
23733828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
23740c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
23750c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
23763828260eSStefano Zampini               total_count_recv[j]+=1;
23770c7d97c5SJed Brown             }
23780c7d97c5SJed Brown           }
23790c7d97c5SJed Brown         }
2380da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
23813828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
23823828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
23833828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
23843828260eSStefano Zampini           }
23853828260eSStefano Zampini           printf("\n");
2386da1bb401SStefano Zampini         }*/
23870c7d97c5SJed Brown 
23880c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
23890bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
23900bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
23910bdf917eSStefano Zampini         }
2392da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2393674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
23943828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
23953828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
23963828260eSStefano Zampini           } else {
23973828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
23983828260eSStefano Zampini           }
2399da1bb401SStefano Zampini         printf("\n");*/
24000c7d97c5SJed Brown       }
24010c7d97c5SJed Brown 
24020c7d97c5SJed Brown       /* Scatter new decomposition for send details */
240353cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
24040c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
24050c7d97c5SJed Brown       if ( coarse_color == 0) {
240653cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
24070c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
240853cdbc3dSStefano 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);
24090c7d97c5SJed Brown       }
24100c7d97c5SJed Brown 
2411da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2412da1bb401SStefano Zampini       if (coarse_color == 0) {
2413da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2414da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
2415da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2416da1bb401SStefano Zampini         printf("\n");
2417da1bb401SStefano Zampini       }*/
24180c7d97c5SJed Brown 
24190c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24200bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2421da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
24220bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
24230c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
24240c7d97c5SJed Brown       }
24250c7d97c5SJed Brown       break;
24260c7d97c5SJed Brown     }
24270c7d97c5SJed Brown 
24280c7d97c5SJed Brown     case(REPLICATED_BDDC):
24290c7d97c5SJed Brown 
24300c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
24310c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
24320c7d97c5SJed Brown       coarse_pc_type  = PCLU;
243353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24340c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
24350c7d97c5SJed Brown       active_rank = rank_prec_comm;
24360c7d97c5SJed Brown       break;
24370c7d97c5SJed Brown 
24380c7d97c5SJed Brown     case(PARALLEL_BDDC):
24390c7d97c5SJed Brown 
24400c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2441674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
24420c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
244353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24440c7d97c5SJed Brown       coarse_comm = prec_comm;
24450c7d97c5SJed Brown       active_rank = rank_prec_comm;
24460c7d97c5SJed Brown       break;
24470c7d97c5SJed Brown 
24480c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
24490c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
2450674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
24510c7d97c5SJed Brown       coarse_pc_type = PCLU;
245253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24530c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
24540c7d97c5SJed Brown       active_rank = master_proc;
24550c7d97c5SJed Brown       break;
24560c7d97c5SJed Brown   }
24570c7d97c5SJed Brown 
24580c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
24590c7d97c5SJed Brown 
24600c7d97c5SJed Brown     case(SCATTERS_BDDC):
24610c7d97c5SJed Brown       {
24620c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
24630c7d97c5SJed Brown 
24642e8d2280SStefano Zampini           IS coarse_IS;
24652e8d2280SStefano Zampini 
2466523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2467523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2468523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
2469523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2470523858cfSStefano Zampini             /* nonzeros */
2471523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2472523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2473523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2474523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
2475523858cfSStefano Zampini             }
2476523858cfSStefano Zampini           } else {
24770c7d97c5SJed Brown             PetscMPIInt send_size;
2478ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
24790c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
24800c7d97c5SJed Brown             PetscInt    ii,jj;
24810c7d97c5SJed Brown             MPI_Request *requests;
2482ef028eecSStefano Zampini 
2483523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2484523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
2485523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
2486523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2487523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
2488523858cfSStefano Zampini             j = 0;
2489523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2490523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
2491523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
2492523858cfSStefano Zampini             }
2493523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
2494523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
24950c7d97c5SJed Brown             /* allocate auxiliary space */
2496523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
24970c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
24980c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
24990c7d97c5SJed Brown             /* allocate stuffs for message massing */
25000c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2501523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2502523858cfSStefano Zampini             /* send indices to be inserted */
2503523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2504523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
2505523858cfSStefano 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);
2506523858cfSStefano Zampini             }
2507523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2508523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
2509ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2510ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
2511ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
2512ef028eecSStefano Zampini               }
2513ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2514523858cfSStefano Zampini             }
2515523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2516ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2517ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2518ef028eecSStefano Zampini             }
25190c7d97c5SJed Brown             j = 0;
25200c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
25212e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
25222e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
25230c7d97c5SJed Brown               localdispl2[i] = j;
25240c7d97c5SJed Brown               j += localsizes2[i];
2525523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
25264fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
25272e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
25284fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
25290c7d97c5SJed Brown               }
25304fad6a16SStefano Zampini             }
2531523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
25320c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
25330c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
25340c7d97c5SJed Brown             ins_local_primal_size = 0;
2535ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
2536ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
25370c7d97c5SJed Brown                 ins_local_primal_size++;
2538ea7e1babSStefano Zampini               }
2539ea7e1babSStefano Zampini             }
25400c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
25410c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
25420c7d97c5SJed Brown             j = 0;
2543ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
2544ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
25452e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
25462e8d2280SStefano Zampini                 j++;
2547ea7e1babSStefano Zampini               }
2548ea7e1babSStefano Zampini             }
2549523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2550523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2551523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2552523858cfSStefano Zampini             }
2553523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2554523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2555523858cfSStefano 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);
2556523858cfSStefano Zampini             }
2557523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2558523858cfSStefano Zampini             /* nonzeros */
2559523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2560523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
25610c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
25620c7d97c5SJed Brown             j=0;
25630c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
25640c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
25650c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
25660c7d97c5SJed Brown               } else {
25670c7d97c5SJed Brown                 aux_ins_indices[i]=j;
25680c7d97c5SJed Brown                 j++;
25690c7d97c5SJed Brown               }
25700c7d97c5SJed Brown             }
25714fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
2572523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
2573523858cfSStefano Zampini               for (k=0;k<j;k++) {
2574523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
25750c7d97c5SJed Brown               }
25760c7d97c5SJed Brown             }
2577523858cfSStefano Zampini             /* check */
2578523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2579523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2580523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
25810c7d97c5SJed Brown               }
25820c7d97c5SJed Brown             }
25830c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
25840c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
25850c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
25864fad6a16SStefano Zampini           }
25870c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
2588142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
25890c7d97c5SJed Brown           coarse_comm = prec_comm;
25900c7d97c5SJed Brown           active_rank = rank_prec_comm;
25910c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
25920c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
25930c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
25942e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
25950c7d97c5SJed Brown           /* arrays for values insertion */
25960c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
25972e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
25980c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
25990c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
26000c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
26014fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
26024fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
26034fad6a16SStefano Zampini             }
26040c7d97c5SJed Brown           }
26050c7d97c5SJed Brown         }
26060c7d97c5SJed Brown         break;
2607674ae819SStefano Zampini 
26080c7d97c5SJed Brown     }
26090c7d97c5SJed Brown 
26100c7d97c5SJed Brown     case(GATHERS_BDDC):
26110c7d97c5SJed Brown       {
2612674ae819SStefano Zampini 
26130c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
2614ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
26150c7d97c5SJed Brown 
26160c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
26170c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
26180bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
26190c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
26200c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
26210c7d97c5SJed Brown           /* arrays for values insertion */
26222fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
26230c7d97c5SJed Brown           localdispl2[0]=0;
26242fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
26250c7d97c5SJed Brown           j=0;
26262fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
26270c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
26280c7d97c5SJed Brown         }
26290c7d97c5SJed Brown 
26300c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
26310c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2632ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
26332fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
26342fa5cd67SKarl Rupp 
26350c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2636ef028eecSStefano 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);
263753cdbc3dSStefano 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);
26380c7d97c5SJed Brown         } else {
2639ef028eecSStefano 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);
264053cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
26410c7d97c5SJed Brown         }
2642ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
26430c7d97c5SJed Brown         break;
2644da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
26450c7d97c5SJed Brown   }
26460c7d97c5SJed Brown 
26470c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
26480c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2649142dfd88SStefano Zampini 
2650142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2651142dfd88SStefano Zampini 
26520c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
26530c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
26540c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
26550c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2656674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2657674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
26583b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2659da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
26603b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
26610c7d97c5SJed Brown     } else {
26624fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
26633b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
26640c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2665674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2666674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
26673b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2668da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2669a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
26700c7d97c5SJed Brown     }
2671142dfd88SStefano Zampini     /* preallocation */
2672142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2673ef028eecSStefano Zampini 
2674674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2675ef028eecSStefano Zampini 
2676142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2677142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2678674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2679ef028eecSStefano Zampini 
2680142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2681ef028eecSStefano Zampini 
2682ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2683ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2684ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2685ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2686ef028eecSStefano Zampini 
2687ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2688674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2689ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2690ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2691ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2692ef028eecSStefano Zampini 
2693ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2694ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2695ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2696ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2697ef028eecSStefano Zampini 
2698ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2699ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2700142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2701ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2702ef028eecSStefano Zampini             row_ownership[j]=i;
2703142dfd88SStefano Zampini           }
2704142dfd88SStefano Zampini         }
2705ef028eecSStefano Zampini 
2706ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2707ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2708ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2709ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2710ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2711ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2712ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2713ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2714142dfd88SStefano Zampini             } else {
2715ef028eecSStefano Zampini               my_onz[i] += 1.0;
2716142dfd88SStefano Zampini             }
2717ef028eecSStefano Zampini             if (i != j) {
2718ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2719ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2720ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2721142dfd88SStefano Zampini               } else {
2722ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2723142dfd88SStefano Zampini               }
2724142dfd88SStefano Zampini             }
2725142dfd88SStefano Zampini           }
2726142dfd88SStefano Zampini         }
2727ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2728ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2729a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2730ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2731ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2732a929c220SStefano Zampini         }
2733ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2734ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2735ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2736ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2737ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2738ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
27392fa5cd67SKarl Rupp         for (i=0; i<j; i++) dnz[i] = (PetscInt)array[i];
27402fa5cd67SKarl Rupp 
2741ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2742ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
27432fa5cd67SKarl Rupp         for (i=0;i<j;i++) onz[i] = (PetscInt)array[i];
27442fa5cd67SKarl Rupp 
2745ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2746ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2747ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2748ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2749ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2750ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2751142dfd88SStefano Zampini       } else {
2752142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2753142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2754142dfd88SStefano Zampini           offset2=localdispl2[k];
2755142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2756ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2757ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2758ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2759ef028eecSStefano Zampini           }
2760142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2761142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2762142dfd88SStefano Zampini           }
2763ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2764142dfd88SStefano Zampini         }
2765142dfd88SStefano Zampini       }
27662fa5cd67SKarl Rupp 
2767142dfd88SStefano Zampini       /* check */
2768142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
27692fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
27702fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2771142dfd88SStefano Zampini       }
2772d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2773d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2774142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2775142dfd88SStefano Zampini     } else {
2776523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2777523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2778142dfd88SStefano Zampini     }
2779142dfd88SStefano Zampini     /* insert values */
2780523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
27810c7d97c5SJed 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);
2782523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2783523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2784523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2785523858cfSStefano 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);
2786523858cfSStefano Zampini       } else {
2787523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2788523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2789523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2790523858cfSStefano Zampini           offset2 = localdispl2[k];
2791523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2792ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2793ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2794ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2795ef028eecSStefano Zampini           }
2796523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2797523858cfSStefano 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);
2798ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2799523858cfSStefano Zampini         }
2800523858cfSStefano Zampini       }
2801523858cfSStefano Zampini       ins_local_primal_indices = 0;
2802523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2803ea7e1babSStefano Zampini     } else {
2804ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2805ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2806ea7e1babSStefano Zampini         offset2=localdispl2[k];
2807ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2808ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2809ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2810ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2811ef028eecSStefano Zampini         }
2812ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2813ea7e1babSStefano 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);
2814ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2815ea7e1babSStefano Zampini       }
2816ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2817ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2818ea7e1babSStefano Zampini     }
28190c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28200c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2821142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2822142dfd88SStefano Zampini     if (issym) {
2823142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2824142dfd88SStefano Zampini     }
28250c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
28260bdf917eSStefano Zampini   }
28270bdf917eSStefano Zampini 
28280bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
28290bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
28300bdf917eSStefano Zampini      IS local_IS,global_IS;
28310bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
28320bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
28330bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
28340bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
28350bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
28360bdf917eSStefano Zampini   }
28370bdf917eSStefano Zampini 
2838a929c220SStefano Zampini   /* free memory no longer needed */
2839a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2840a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2841a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2842a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2843a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2844a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2845a929c220SStefano Zampini 
2846674ae819SStefano Zampini   /* Compute coarse null space */
2847674ae819SStefano Zampini   CoarseNullSpace = 0;
28480bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2849674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
28500bdf917eSStefano Zampini   }
28510bdf917eSStefano Zampini 
28520bdf917eSStefano Zampini   /* KSP for coarse problem */
28530bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
28542e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
28550bdf917eSStefano Zampini 
285653cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
285753cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
285853cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
28593b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
286053cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
286153cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
286253cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
28630c7d97c5SJed Brown     /* Allow user's customization */
2864da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
28650c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
286653cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
28674fad6a16SStefano Zampini       i = pcbddc->current_level+1;
28684fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
28694fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
28704fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
287153cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2872674ae819SStefano Zampini       if (CoarseNullSpace) {
2873674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2874674ae819SStefano Zampini       }
28754fad6a16SStefano Zampini       if (dbg_flag) {
28764fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
28774fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
287853cdbc3dSStefano Zampini       }
2879674ae819SStefano Zampini     } else {
2880674ae819SStefano Zampini       if (CoarseNullSpace) {
2881674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2882674ae819SStefano Zampini       }
28834fad6a16SStefano Zampini     }
28844fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
288553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2886142dfd88SStefano Zampini 
28870298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
28882e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
28892e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
28902e8d2280SStefano Zampini     if (j == 1) {
28912e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
28922e8d2280SStefano Zampini       if (isbddc) {
28932e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
28945619798eSStefano Zampini       }
28955619798eSStefano Zampini     }
28960c7d97c5SJed Brown   }
2897a929c220SStefano Zampini   /* Check coarse problem if requested */
2898142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2899142dfd88SStefano Zampini     KSP check_ksp;
2900142dfd88SStefano Zampini     PC  check_pc;
2901142dfd88SStefano Zampini     Vec check_vec;
2902142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
290319fd82e9SBarry Smith     KSPType check_ksp_type;
29040c7d97c5SJed Brown 
2905142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2906142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2907142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
29080bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2909142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
29102fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
29112fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2912142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2913142dfd88SStefano Zampini     } else {
2914142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2915142dfd88SStefano Zampini     }
2916142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2917142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2918142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2919142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2920142dfd88SStefano Zampini     /* create random vec */
2921142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
29220298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2923674ae819SStefano Zampini     if (CoarseNullSpace) {
2924674ae819SStefano Zampini       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec,NULL);CHKERRQ(ierr);
2925674ae819SStefano Zampini     }
2926142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2927142dfd88SStefano Zampini     /* solve coarse problem */
2928142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2929674ae819SStefano Zampini     if (CoarseNullSpace) {
2930674ae819SStefano Zampini       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
2931674ae819SStefano Zampini     }
2932142dfd88SStefano Zampini     /* check coarse problem residual error */
2933142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2934142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2935142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2936142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2937142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2938142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2939142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2940142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2941142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2942142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2943e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
29443b03a366Sstefano_zampini     }
2945142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2946142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2947142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
294853cdbc3dSStefano Zampini   }
2949674ae819SStefano Zampini   if (dbg_flag) {
2950da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2951da1bb401SStefano Zampini   }
2952674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2953a0ba757dSStefano Zampini 
29540c7d97c5SJed Brown   PetscFunctionReturn(0);
29550c7d97c5SJed Brown }
29560c7d97c5SJed Brown 
2957