xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 3308cffd9d048811e7d2043e2ace7cce471f9e00)
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 */
439d9e44b6SStefano 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);
455fb223d50SStefano Zampini   /* TODO: PCBDDCGraphSetAdjacency */
456674ae819SStefano Zampini   /* get CSR into graph structure */
457da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
458674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
460674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
461674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
462da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4631a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4641a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
465674ae819SStefano Zampini   }
466575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46736e030ebSStefano Zampini   PetscFunctionReturn(0);
46836e030ebSStefano Zampini }
4691e6b0712SBarry Smith 
47036e030ebSStefano Zampini #undef __FUNCT__
471da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
47236e030ebSStefano Zampini /*@
473da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47436e030ebSStefano Zampini 
47536e030ebSStefano Zampini    Not collective
47636e030ebSStefano Zampini 
47736e030ebSStefano Zampini    Input Parameters:
47836e030ebSStefano Zampini +  pc - the preconditioning context
479da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
480da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
481da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
482da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48336e030ebSStefano Zampini 
48436e030ebSStefano Zampini    Level: intermediate
48536e030ebSStefano Zampini 
48636e030ebSStefano Zampini    Notes:
48736e030ebSStefano Zampini 
48836e030ebSStefano Zampini .seealso: PCBDDC
48936e030ebSStefano Zampini @*/
4901a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
49136e030ebSStefano Zampini {
492575ad6abSStefano Zampini   void (*f)(void) = 0;
49336e030ebSStefano Zampini   PetscErrorCode ierr;
49436e030ebSStefano Zampini 
49536e030ebSStefano Zampini   PetscFunctionBegin;
49636e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
497674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
498674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
499674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
500674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
501da1bb401SStefano Zampini   }
50236e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
503575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
504575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
505575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
506575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
507575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50836e030ebSStefano Zampini   }
50936e030ebSStefano Zampini   PetscFunctionReturn(0);
51036e030ebSStefano Zampini }
5119c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5121e6b0712SBarry Smith 
5139c0446d6SStefano Zampini #undef __FUNCT__
5149c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5159c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5169c0446d6SStefano Zampini {
5179c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5189c0446d6SStefano Zampini   PetscInt i;
5199c0446d6SStefano Zampini   PetscErrorCode ierr;
5209c0446d6SStefano Zampini 
5219c0446d6SStefano Zampini   PetscFunctionBegin;
522da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5239c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5249c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5259c0446d6SStefano Zampini   }
526d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
527da1bb401SStefano Zampini   /* allocate space then set */
5289c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5299c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
530da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
531da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5329c0446d6SStefano Zampini   }
5339c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5349c0446d6SStefano Zampini   PetscFunctionReturn(0);
5359c0446d6SStefano Zampini }
5361e6b0712SBarry Smith 
5379c0446d6SStefano Zampini #undef __FUNCT__
5389c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5399c0446d6SStefano Zampini /*@
540da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5419c0446d6SStefano Zampini 
5429c0446d6SStefano Zampini    Not collective
5439c0446d6SStefano Zampini 
5449c0446d6SStefano Zampini    Input Parameters:
5459c0446d6SStefano Zampini +  pc - the preconditioning context
546da1bb401SStefano Zampini -  n - number of index sets defining the fields
547da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5489c0446d6SStefano Zampini 
5499c0446d6SStefano Zampini    Level: intermediate
5509c0446d6SStefano Zampini 
5519c0446d6SStefano Zampini    Notes:
5529c0446d6SStefano Zampini 
5539c0446d6SStefano Zampini .seealso: PCBDDC
5549c0446d6SStefano Zampini @*/
5559c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5569c0446d6SStefano Zampini {
5579c0446d6SStefano Zampini   PetscErrorCode ierr;
5589c0446d6SStefano Zampini 
5599c0446d6SStefano Zampini   PetscFunctionBegin;
5609c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5619c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5629c0446d6SStefano Zampini   PetscFunctionReturn(0);
5639c0446d6SStefano Zampini }
564da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
565534831adSStefano Zampini #undef __FUNCT__
566534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
567534831adSStefano Zampini /* -------------------------------------------------------------------------- */
568534831adSStefano Zampini /*
569534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
570534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5719c0446d6SStefano Zampini 
572534831adSStefano Zampini    Input Parameter:
573534831adSStefano Zampini +  pc - the preconditioner contex
574534831adSStefano Zampini 
575534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
576534831adSStefano Zampini 
577534831adSStefano Zampini    Notes:
578534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
579534831adSStefano Zampini    the user, but instead is called by KSPSolve().
580534831adSStefano Zampini */
581534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
582534831adSStefano Zampini {
583534831adSStefano Zampini   PetscErrorCode ierr;
584534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
585534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
586534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
587534831adSStefano Zampini   Mat            temp_mat;
5883972b0daSStefano Zampini   IS             dirIS;
5893972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5903972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5913972b0daSStefano Zampini   Vec            used_vec;
5923972b0daSStefano Zampini   PetscBool      guess_nonzero;
593534831adSStefano Zampini 
594534831adSStefano Zampini   PetscFunctionBegin;
5953972b0daSStefano Zampini   if (x) {
5963972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
5973972b0daSStefano Zampini     used_vec = x;
5983972b0daSStefano Zampini   } else {
5993972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
6003972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
6013972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6023972b0daSStefano Zampini   }
6033972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6043972b0daSStefano Zampini   if (ksp) {
6053972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6063972b0daSStefano Zampini     if ( !guess_nonzero ) {
6073972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6083972b0daSStefano Zampini     }
6093972b0daSStefano Zampini   }
610*3308cffdSStefano Zampini 
611*3308cffdSStefano Zampini   if (rhs) {
6123972b0daSStefano Zampini     /* store the original rhs */
6133972b0daSStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6143972b0daSStefano Zampini 
6153972b0daSStefano Zampini     /* Take into account zeroed rows -> change rhs and store solution removed */
6163972b0daSStefano Zampini     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6173972b0daSStefano Zampini     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6183972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6193972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6203972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6213972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6223972b0daSStefano Zampini     ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6233972b0daSStefano Zampini     if (dirIS) {
6243972b0daSStefano Zampini       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6253972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6263972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6273972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6282fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6293972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6303972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6313972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6323972b0daSStefano Zampini     }
6333972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6343972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
635b76ba322SStefano Zampini 
6363972b0daSStefano Zampini     /* remove the computed solution from the rhs */
6373972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6383972b0daSStefano Zampini     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6393972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
640*3308cffdSStefano Zampini   }
641b76ba322SStefano Zampini 
642b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6433972b0daSStefano Zampini   if (x) {
6443972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6453972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
64615aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
647b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
648b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
649b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
650b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
651b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
652b76ba322SStefano Zampini       if (ksp) {
653b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
654b76ba322SStefano Zampini       }
655b76ba322SStefano Zampini     }
6563972b0daSStefano Zampini   }
657b76ba322SStefano Zampini 
658674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
659b76ba322SStefano Zampini     /* swap pointers for local matrices */
660b76ba322SStefano Zampini     temp_mat = matis->A;
661b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
662b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
663*3308cffdSStefano Zampini   }
664*3308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && rhs) {
665b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
666b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
667b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
668b76ba322SStefano Zampini     /* from original basis to modified basis */
669b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
670b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
671b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
672b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
673674ae819SStefano Zampini   }
6740bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
675d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
676d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
677b76ba322SStefano Zampini   }
6780bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
679534831adSStefano Zampini   PetscFunctionReturn(0);
680534831adSStefano Zampini }
681534831adSStefano Zampini /* -------------------------------------------------------------------------- */
682534831adSStefano Zampini #undef __FUNCT__
683534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
684534831adSStefano Zampini /* -------------------------------------------------------------------------- */
685534831adSStefano Zampini /*
686534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
687534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
688534831adSStefano Zampini 
689534831adSStefano Zampini    Input Parameter:
690534831adSStefano Zampini +  pc - the preconditioner contex
691534831adSStefano Zampini 
692534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
693534831adSStefano Zampini 
694534831adSStefano Zampini    Notes:
695534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
696534831adSStefano Zampini    the user, but instead is called by KSPSolve().
697534831adSStefano Zampini */
698534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
699534831adSStefano Zampini {
700534831adSStefano Zampini   PetscErrorCode ierr;
701534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
702534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
703534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
704534831adSStefano Zampini   Mat            temp_mat;
705534831adSStefano Zampini 
706534831adSStefano Zampini   PetscFunctionBegin;
707*3308cffdSStefano Zampini   if (pcbddc->use_change_of_basis) {
708534831adSStefano Zampini     /* swap pointers for local matrices */
709534831adSStefano Zampini     temp_mat = matis->A;
710534831adSStefano Zampini     matis->A = pcbddc->local_mat;
711534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
712*3308cffdSStefano Zampini   }
713*3308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && x) {
714534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
715534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
716534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
717534831adSStefano Zampini     /* from modified basis to original basis */
718534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
719534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
720534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
721534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
722534831adSStefano Zampini   }
7233972b0daSStefano Zampini   /* add solution removed in presolve */
7243425bc38SStefano Zampini   if (x) {
7253425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7263425bc38SStefano Zampini   }
727fb223d50SStefano Zampini   /* restore rhs to its original state */
728fb223d50SStefano Zampini   if (rhs) {
729fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
730fb223d50SStefano Zampini   }
731534831adSStefano Zampini   PetscFunctionReturn(0);
732534831adSStefano Zampini }
733534831adSStefano Zampini /* -------------------------------------------------------------------------- */
73453cdbc3dSStefano Zampini #undef __FUNCT__
73553cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7360c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7370c7d97c5SJed Brown /*
7380c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7390c7d97c5SJed Brown                   by setting data structures and options.
7400c7d97c5SJed Brown 
7410c7d97c5SJed Brown    Input Parameter:
74253cdbc3dSStefano Zampini +  pc - the preconditioner context
7430c7d97c5SJed Brown 
7440c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7450c7d97c5SJed Brown 
7460c7d97c5SJed Brown    Notes:
7470c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7480c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7490c7d97c5SJed Brown */
75053cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7510c7d97c5SJed Brown {
7520c7d97c5SJed Brown   PetscErrorCode ierr;
7530c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
754674ae819SStefano Zampini   MatStructure   flag;
755674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7560c7d97c5SJed Brown 
7570c7d97c5SJed Brown   PetscFunctionBegin;
758674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7593b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7609c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7610c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7620c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7630c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7643b03a366Sstefano_zampini   /* Get stdout for dbg */
765674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
766ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
767e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
768e269702eSStefano Zampini   }
769674ae819SStefano Zampini   /* first attempt to split work */
770674ae819SStefano Zampini   if (pc->setupcalled) {
771674ae819SStefano Zampini     computeis = PETSC_FALSE;
772674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
773674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
774674ae819SStefano Zampini       computetopography = PETSC_FALSE;
775674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
776674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
777674ae819SStefano Zampini       computetopography = PETSC_FALSE;
778674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
779674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
780674ae819SStefano Zampini       computetopography = PETSC_TRUE;
781674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
782674ae819SStefano Zampini     }
783674ae819SStefano Zampini   } else {
784674ae819SStefano Zampini     computeis = PETSC_TRUE;
785674ae819SStefano Zampini     computetopography = PETSC_TRUE;
786674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
787674ae819SStefano Zampini   }
788674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
789674ae819SStefano Zampini   if (computeis) {
790674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
791674ae819SStefano Zampini   }
792674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
793674ae819SStefano Zampini   if (computetopography) {
794674ae819SStefano Zampini     /* reset data */
795674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
796674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
797674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
798674ae819SStefano Zampini   }
799674ae819SStefano Zampini   if (computesolvers) {
800674ae819SStefano Zampini     /* reset data */
801674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
802674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
8030c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
8040c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
805674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
8060c7d97c5SJed Brown   }
8070c7d97c5SJed Brown   PetscFunctionReturn(0);
8080c7d97c5SJed Brown }
8090c7d97c5SJed Brown 
8100c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8110c7d97c5SJed Brown /*
8120c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8130c7d97c5SJed Brown 
8140c7d97c5SJed Brown    Input Parameters:
8150c7d97c5SJed Brown .  pc - the preconditioner context
8160c7d97c5SJed Brown .  r - input vector (global)
8170c7d97c5SJed Brown 
8180c7d97c5SJed Brown    Output Parameter:
8190c7d97c5SJed Brown .  z - output vector (global)
8200c7d97c5SJed Brown 
8210c7d97c5SJed Brown    Application Interface Routine: PCApply()
8220c7d97c5SJed Brown  */
8230c7d97c5SJed Brown #undef __FUNCT__
8240c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
82553cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8260c7d97c5SJed Brown {
8270c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8280c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8290c7d97c5SJed Brown   PetscErrorCode    ierr;
8303b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8313b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8322617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8330c7d97c5SJed Brown 
8340c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8350c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
83629622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8370c7d97c5SJed Brown 
8380c7d97c5SJed Brown   PetscFunctionBegin;
83915aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8400c7d97c5SJed Brown     /* First Dirichlet solve */
8410c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8420c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
84353cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8440c7d97c5SJed Brown     /*
8450c7d97c5SJed Brown       Assembling right hand side for BDDC operator
846674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
847674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8480c7d97c5SJed Brown     */
8490c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8500c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
85129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8520c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8530c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8540c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8550c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
856674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
857b76ba322SStefano Zampini   } else {
8580bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
859b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
860674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
861b76ba322SStefano Zampini   }
862b76ba322SStefano Zampini 
8632617d88aSStefano Zampini   /* Apply interface preconditioner
8642617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8652617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8662617d88aSStefano Zampini 
867674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
868674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8690c7d97c5SJed Brown 
8703b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8710c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8720c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8730c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
87429622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
87553cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8760c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
87729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8780c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8790c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8800c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8810c7d97c5SJed Brown   PetscFunctionReturn(0);
8820c7d97c5SJed Brown }
883da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
884674ae819SStefano Zampini 
885da1bb401SStefano Zampini #undef __FUNCT__
886da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
887da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
888da1bb401SStefano Zampini {
889da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
890da1bb401SStefano Zampini   PetscErrorCode ierr;
891da1bb401SStefano Zampini 
892da1bb401SStefano Zampini   PetscFunctionBegin;
893da1bb401SStefano Zampini   /* free data created by PCIS */
894da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
895674ae819SStefano Zampini   /* free BDDC custom data  */
896674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
897674ae819SStefano Zampini   /* destroy objects related to topography */
898674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
899674ae819SStefano Zampini   /* free allocated graph structure */
900da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
901674ae819SStefano Zampini   /* free data for scaling operator */
902674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
903674ae819SStefano Zampini   /* free solvers stuff */
904674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
9053425bc38SStefano Zampini   /* remove functions */
906674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
907bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
908bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
909bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
910bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
911bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
912bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
913bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
914bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
915bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
916bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
917bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
918bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
919bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
920674ae819SStefano Zampini   /* Free the private data structure */
921674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
922da1bb401SStefano Zampini   PetscFunctionReturn(0);
923da1bb401SStefano Zampini }
9243425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9251e6b0712SBarry Smith 
9263425bc38SStefano Zampini #undef __FUNCT__
9273425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9283425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9293425bc38SStefano Zampini {
930674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9313425bc38SStefano Zampini   PC_IS*         pcis;
9323425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9333425bc38SStefano Zampini   PetscErrorCode ierr;
9340c7d97c5SJed Brown 
9353425bc38SStefano Zampini   PetscFunctionBegin;
9363425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9373425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9383425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9393425bc38SStefano Zampini 
9403425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9413425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
942*3308cffdSStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
9433425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9443425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9453425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
946fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
947fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
9483425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9493425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
950674ae819SStefano Zampini   /* Apply partition of unity */
9513425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
952674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
95329622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9543425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9553425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9563425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9573425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9583425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9593425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9603425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
961674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9623425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9633425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9643425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9653425bc38SStefano Zampini   }
9663425bc38SStefano Zampini   /* BDDC rhs */
9673425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
96829622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9693425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9703425bc38SStefano Zampini   }
9713425bc38SStefano Zampini   /* apply BDDC */
9723425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9733425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9743425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9753425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9763425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9773425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9783425bc38SStefano Zampini   /* restore original rhs */
9793425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9803425bc38SStefano Zampini   PetscFunctionReturn(0);
9813425bc38SStefano Zampini }
9821e6b0712SBarry Smith 
9833425bc38SStefano Zampini #undef __FUNCT__
9843425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9853425bc38SStefano Zampini /*@
9863425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9873425bc38SStefano Zampini 
9883425bc38SStefano Zampini    Collective
9893425bc38SStefano Zampini 
9903425bc38SStefano Zampini    Input Parameters:
9913425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
9923425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
9933425bc38SStefano Zampini 
9943425bc38SStefano Zampini    Output Parameters:
9953425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
9963425bc38SStefano Zampini 
9973425bc38SStefano Zampini    Level: developer
9983425bc38SStefano Zampini 
9993425bc38SStefano Zampini    Notes:
10003425bc38SStefano Zampini 
10013425bc38SStefano Zampini .seealso: PCBDDC
10023425bc38SStefano Zampini @*/
10033425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
10043425bc38SStefano Zampini {
1005674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10063425bc38SStefano Zampini   PetscErrorCode ierr;
10073425bc38SStefano Zampini 
10083425bc38SStefano Zampini   PetscFunctionBegin;
10093425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10103425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10113425bc38SStefano Zampini   PetscFunctionReturn(0);
10123425bc38SStefano Zampini }
10133425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10141e6b0712SBarry Smith 
10153425bc38SStefano Zampini #undef __FUNCT__
10163425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10173425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10183425bc38SStefano Zampini {
1019674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10203425bc38SStefano Zampini   PC_IS*         pcis;
10213425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10223425bc38SStefano Zampini   PetscErrorCode ierr;
10233425bc38SStefano Zampini 
10243425bc38SStefano Zampini   PetscFunctionBegin;
10253425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10263425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10273425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10283425bc38SStefano Zampini 
10293425bc38SStefano Zampini   /* apply B_delta^T */
10303425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10313425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10323425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10333425bc38SStefano Zampini   /* compute rhs for BDDC application */
10343425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
103529622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10363425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10373425bc38SStefano Zampini   }
10383425bc38SStefano Zampini   /* apply BDDC */
10393425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10403425bc38SStefano Zampini   /* put values into standard global vector */
10413425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10423425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
104329622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10443425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10453425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10463425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10473425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10483425bc38SStefano Zampini   }
10493425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10503425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10513425bc38SStefano Zampini   /* final change of basis if needed
10523425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
1053*3308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
10543425bc38SStefano Zampini   PetscFunctionReturn(0);
10553425bc38SStefano Zampini }
10561e6b0712SBarry Smith 
10573425bc38SStefano Zampini #undef __FUNCT__
10583425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10593425bc38SStefano Zampini /*@
10603425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10613425bc38SStefano Zampini 
10623425bc38SStefano Zampini    Collective
10633425bc38SStefano Zampini 
10643425bc38SStefano Zampini    Input Parameters:
10653425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10663425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10673425bc38SStefano Zampini 
10683425bc38SStefano Zampini    Output Parameters:
10693425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10703425bc38SStefano Zampini 
10713425bc38SStefano Zampini    Level: developer
10723425bc38SStefano Zampini 
10733425bc38SStefano Zampini    Notes:
10743425bc38SStefano Zampini 
10753425bc38SStefano Zampini .seealso: PCBDDC
10763425bc38SStefano Zampini @*/
10773425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10783425bc38SStefano Zampini {
1079674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10803425bc38SStefano Zampini   PetscErrorCode ierr;
10813425bc38SStefano Zampini 
10823425bc38SStefano Zampini   PetscFunctionBegin;
10833425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10843425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10853425bc38SStefano Zampini   PetscFunctionReturn(0);
10863425bc38SStefano Zampini }
10873425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10881e6b0712SBarry Smith 
1089f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1090f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1091f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1092f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1093674ae819SStefano Zampini 
10943425bc38SStefano Zampini #undef __FUNCT__
10953425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
10963425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
10973425bc38SStefano Zampini {
1098674ae819SStefano Zampini 
1099674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
11003425bc38SStefano Zampini   Mat            newmat;
1101674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
11023425bc38SStefano Zampini   PC             newpc;
1103ce94432eSBarry Smith   MPI_Comm       comm;
11043425bc38SStefano Zampini   PetscErrorCode ierr;
11053425bc38SStefano Zampini 
11063425bc38SStefano Zampini   PetscFunctionBegin;
1107ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
11083425bc38SStefano Zampini   /* FETIDP linear matrix */
11093425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11103425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11113425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11123425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11133425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11143425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11153425bc38SStefano Zampini   /* FETIDP preconditioner */
11163425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11173425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11183425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11193425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11203425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11213425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11223425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11233425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11243425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11253425bc38SStefano Zampini   /* return pointers for objects created */
11263425bc38SStefano Zampini   *fetidp_mat=newmat;
11273425bc38SStefano Zampini   *fetidp_pc=newpc;
11283425bc38SStefano Zampini   PetscFunctionReturn(0);
11293425bc38SStefano Zampini }
11301e6b0712SBarry Smith 
11313425bc38SStefano Zampini #undef __FUNCT__
11323425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11333425bc38SStefano Zampini /*@
11343425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11353425bc38SStefano Zampini 
11363425bc38SStefano Zampini    Collective
11373425bc38SStefano Zampini 
11383425bc38SStefano Zampini    Input Parameters:
11393425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11403425bc38SStefano Zampini 
11413425bc38SStefano Zampini    Level: developer
11423425bc38SStefano Zampini 
11433425bc38SStefano Zampini    Notes:
11443425bc38SStefano Zampini 
11453425bc38SStefano Zampini .seealso: PCBDDC
11463425bc38SStefano Zampini @*/
11473425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11483425bc38SStefano Zampini {
11493425bc38SStefano Zampini   PetscErrorCode ierr;
11503425bc38SStefano Zampini 
11513425bc38SStefano Zampini   PetscFunctionBegin;
11523425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11533425bc38SStefano Zampini   if (pc->setupcalled) {
11543425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1155f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11563425bc38SStefano Zampini   PetscFunctionReturn(0);
11573425bc38SStefano Zampini }
11580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1159da1bb401SStefano Zampini /*MC
1160da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11610c7d97c5SJed Brown 
1162da1bb401SStefano Zampini    Options Database Keys:
1163da1bb401SStefano Zampini .    -pcbddc ??? -
1164da1bb401SStefano Zampini 
1165da1bb401SStefano Zampini    Level: intermediate
1166da1bb401SStefano Zampini 
1167da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1168da1bb401SStefano Zampini 
1169da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1170da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1171da1bb401SStefano Zampini           on the subdomains).
1172da1bb401SStefano Zampini 
1173da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1174da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1175da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1176da1bb401SStefano Zampini 
1177da1bb401SStefano Zampini    Contributed by Stefano Zampini
1178da1bb401SStefano Zampini 
1179da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1180da1bb401SStefano Zampini M*/
1181b2573a8aSBarry Smith 
1182da1bb401SStefano Zampini #undef __FUNCT__
1183da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11848cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1185da1bb401SStefano Zampini {
1186da1bb401SStefano Zampini   PetscErrorCode      ierr;
1187da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1188da1bb401SStefano Zampini 
1189da1bb401SStefano Zampini   PetscFunctionBegin;
1190da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1191da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1192da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1193da1bb401SStefano Zampini 
1194da1bb401SStefano Zampini   /* create PCIS data structure */
1195da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1196da1bb401SStefano Zampini 
1197da1bb401SStefano Zampini   /* BDDC specific */
1198674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
11990bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
12003972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1201534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1202534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1203534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1204674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1205674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1206da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1207da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1208da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1209da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1210da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
121115aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
121215aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
1213da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1214da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1215da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1216da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1217da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1218da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1219da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1220da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1221da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1222da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
122329622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1224da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1225da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1226da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1227da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1228da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1229da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1230da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
12319d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1232da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1233b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12344fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12354fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1236674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1237674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1238da1bb401SStefano Zampini 
1239674ae819SStefano Zampini   /* create local graph structure */
1240674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1241674ae819SStefano Zampini 
1242674ae819SStefano Zampini   /* scaling */
1243674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1244674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1245da1bb401SStefano Zampini 
1246da1bb401SStefano Zampini   /* function pointers */
1247da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1248da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1249da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1250da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1251da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1252da1bb401SStefano Zampini   pc->ops->view                = 0;
1253da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1254da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1255da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1256534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1257534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1258da1bb401SStefano Zampini 
1259da1bb401SStefano Zampini   /* composing function */
1260674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1261bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1262bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1263bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1264bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1265bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1266bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1267bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1268bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1269bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1270bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1271bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1274da1bb401SStefano Zampini   PetscFunctionReturn(0);
1275da1bb401SStefano Zampini }
12763425bc38SStefano Zampini 
1277da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1278da1bb401SStefano Zampini /* All static functions from now on                                           */
1279da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
128029622bf0SStefano Zampini 
128129622bf0SStefano Zampini #undef __FUNCT__
12822e8d2280SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
12832e8d2280SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool use)
12842e8d2280SStefano Zampini {
12852e8d2280SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12862e8d2280SStefano Zampini 
12872e8d2280SStefano Zampini   PetscFunctionBegin;
12882e8d2280SStefano Zampini   pcbddc->use_exact_dirichlet=use;
12892e8d2280SStefano Zampini   PetscFunctionReturn(0);
12902e8d2280SStefano Zampini }
12912e8d2280SStefano Zampini 
12922e8d2280SStefano Zampini #undef __FUNCT__
12934fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12944fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12954fad6a16SStefano Zampini {
12964fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12974fad6a16SStefano Zampini 
12984fad6a16SStefano Zampini   PetscFunctionBegin;
12994fad6a16SStefano Zampini   pcbddc->current_level=level;
13004fad6a16SStefano Zampini   PetscFunctionReturn(0);
13014fad6a16SStefano Zampini }
13023425bc38SStefano Zampini 
13033b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
13040c7d97c5SJed Brown #undef __FUNCT__
13050c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
130653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
13070c7d97c5SJed Brown {
13080c7d97c5SJed Brown   PetscErrorCode  ierr;
1309674ae819SStefano Zampini 
13100c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
13110c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
13120c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
13130c7d97c5SJed Brown   IS                is_R_local;
131419fd82e9SBarry Smith   VecType           impVecType;
131519fd82e9SBarry Smith   MatType           impMatType;
13160c7d97c5SJed Brown   PetscInt          n_R=0;
13170c7d97c5SJed Brown   PetscInt          n_D=0;
13180c7d97c5SJed Brown   PetscInt          n_B=0;
13190c7d97c5SJed Brown   PetscScalar       zero=0.0;
13200c7d97c5SJed Brown   PetscScalar       one=1.0;
13210c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
13220c7d97c5SJed Brown   PetscScalar*      array;
13230c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
13240c7d97c5SJed Brown   PetscInt          *idx_R_local;
13255b08dc53SStefano Zampini   PetscReal         *coarsefunctions_errors,*constraints_errors;
13260c7d97c5SJed Brown   /* auxiliary indices */
1327534831adSStefano Zampini   PetscInt          i,j,k;
1328e269702eSStefano Zampini   /* for verbose output of bddc */
1329e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
13305b08dc53SStefano Zampini   PetscInt          dbg_flag=pcbddc->dbg_flag;
1331a0ba757dSStefano Zampini   /* for counting coarse dofs */
1332534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
13333b03a366Sstefano_zampini   PetscInt          size_of_constraint;
13343b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
13353b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1336e6872a76SStefano Zampini   PetscInt          *vertices;
13370c7d97c5SJed Brown 
13380c7d97c5SJed Brown   PetscFunctionBegin;
13390c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
13400c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
1341534831adSStefano Zampini 
1342534831adSStefano Zampini   /* transform local matrices if needed */
1343674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
1344e6872a76SStefano Zampini     Mat      change_mat_all;
1345e6872a76SStefano Zampini     PetscInt *nnz,*is_indices,*temp_indices;
1346e6872a76SStefano Zampini 
1347534831adSStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1348534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13492fa5cd67SKarl Rupp     for (i=0;i<n_D;i++) nnz[is_indices[i]] = 1;
1350534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1351534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1352534831adSStefano Zampini     k=1;
1353534831adSStefano Zampini     for (i=0;i<n_B;i++) {
13540298fd71SBarry Smith       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1355534831adSStefano Zampini       nnz[is_indices[i]]=j;
13562fa5cd67SKarl Rupp       if (k < j) k = j;
13570298fd71SBarry Smith       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1358534831adSStefano Zampini     }
1359534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1360534831adSStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
1361534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
1362534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
1363534831adSStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
1364534831adSStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
1365534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
1366534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1367534831adSStefano Zampini     for (i=0;i<n_D;i++) {
1368534831adSStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
1369534831adSStefano Zampini     }
1370534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1371534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1372534831adSStefano Zampini     for (i=0;i<n_B;i++) {
1373534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
13742fa5cd67SKarl Rupp       for (k=0; k<j; k++) temp_indices[k]=is_indices[row_cmat_indices[k]];
1375534831adSStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
1376534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
1377534831adSStefano Zampini     }
1378534831adSStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1379534831adSStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13805ce978abSStefano Zampini     /* TODO: HOW TO WORK WITH BAIJ? PtAP not provided */
13815ce978abSStefano Zampini     ierr = MatGetBlockSize(matis->A,&i);CHKERRQ(ierr);
13825ce978abSStefano Zampini     if (i==1) {
1383534831adSStefano Zampini       ierr = MatPtAP(matis->A,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13845ce978abSStefano Zampini     } else {
13855ce978abSStefano Zampini       Mat work_mat;
13865ce978abSStefano Zampini       ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
13875ce978abSStefano Zampini       ierr = MatPtAP(work_mat,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13885ce978abSStefano Zampini       ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
13895ce978abSStefano Zampini     }
1390534831adSStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
1391534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1392534831adSStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
1393534831adSStefano Zampini   } else {
1394534831adSStefano Zampini     /* without change of basis, the local matrix is unchanged */
1395534831adSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1396534831adSStefano Zampini     pcbddc->local_mat = matis->A;
1397534831adSStefano Zampini   }
139815aaf578SStefano Zampini   /* need to rebuild PCIS matrices during SNES or TS -> TODO move this to PCIS code */
139915aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
140015aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
140115aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
140215aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
140315aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
140415aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
1405674ae819SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1406674ae819SStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1407674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
14080bdf917eSStefano Zampini   }
1409a0ba757dSStefano Zampini 
1410e6872a76SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
1411e6872a76SStefano Zampini   impMatType = MATSEQDENSE;
1412e6872a76SStefano Zampini   impVecType = VECSEQ;
1413e6872a76SStefano Zampini   /* get vertex indices from constraint matrix */
1414e6872a76SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1415e6872a76SStefano Zampini   /* Set number of constraints */
1416e6872a76SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
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);
1429e6872a76SStefano Zampini   ierr = PetscFree(vertices);CHKERRQ(ierr);
1430e269702eSStefano Zampini   if (dbg_flag) {
14310c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14320c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14330c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
14340c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
14353b03a366Sstefano_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);
1436534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
14370c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14380c7d97c5SJed Brown   }
1439534831adSStefano Zampini 
14400c7d97c5SJed Brown   /* Allocate needed vectors */
1441534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
14423972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
14430c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
14440c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
14450c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
14460c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1447d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
14480c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
14490c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
14500c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
14510c7d97c5SJed Brown 
14520c7d97c5SJed Brown   /* Creating some index sets needed  */
14530c7d97c5SJed Brown   /* For submatrices */
1454da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
1455da1bb401SStefano Zampini 
14560c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
14570c7d97c5SJed Brown   {
1458e6872a76SStefano Zampini     IS         is_aux1,is_aux2;
14590c7d97c5SJed Brown     PetscInt   *aux_array1;
14600c7d97c5SJed Brown     PetscInt   *aux_array2;
14612e8d2280SStefano Zampini     PetscInt   *idx_I_local;
14620c7d97c5SJed Brown 
14633b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14643b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
14650c7d97c5SJed Brown 
14662e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14670c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14682fa5cd67SKarl Rupp     for (i=0; i<n_D; i++) array[idx_I_local[i]] = 0;
14692e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14702fa5cd67SKarl Rupp     for (i=0, j=0; i<n_R; i++) {
14712fa5cd67SKarl Rupp       if (array[idx_R_local[i]] == one) {
14722fa5cd67SKarl Rupp         aux_array1[j] = i;
14732fa5cd67SKarl Rupp         j++;
14742fa5cd67SKarl Rupp       }
14752fa5cd67SKarl Rupp     }
14760c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1477da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
14782e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14792e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14800c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
14812fa5cd67SKarl Rupp     for (i=0, j=0; i<n_B; i++) {
14822fa5cd67SKarl Rupp       if (array[i] == one) {
14832fa5cd67SKarl Rupp         aux_array2[j] = i; j++;
14842fa5cd67SKarl Rupp       }
14852fa5cd67SKarl Rupp     }
14863828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1487da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
14880c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
14890c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
14900c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
14910c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14920c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
14930c7d97c5SJed Brown 
149429622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
14950c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14960c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14972fa5cd67SKarl Rupp       for (i=0, j=0; i<n_R; i++) {
14982fa5cd67SKarl Rupp         if (array[idx_R_local[i]] == zero) {
14992fa5cd67SKarl Rupp           aux_array1[j] = i;
15002fa5cd67SKarl Rupp           j++;
15012fa5cd67SKarl Rupp         }
15022fa5cd67SKarl Rupp       }
15030c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1504da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
15050c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
15060c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
15070c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
15080c7d97c5SJed Brown     }
15090c7d97c5SJed Brown   }
15100c7d97c5SJed Brown 
15110c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
15120c7d97c5SJed Brown   {
15130c7d97c5SJed Brown     Mat          A_RR;
151453cdbc3dSStefano Zampini     PC           pc_temp;
1515674ae819SStefano Zampini     MatStructure matstruct;
1516674ae819SStefano Zampini     /* Matrix for Dirichlet problem is A_II */
1517674ae819SStefano Zampini     /* HACK (TODO) A_II can be changed between nonlinear iterations */
1518e6872a76SStefano Zampini     if (pc->setupcalled) { /* we dont need to rebuild dirichlet problem the first time we build BDDC */
1519674ae819SStefano Zampini       ierr = PCGetOperators(pc,NULL,NULL,&matstruct);CHKERRQ(ierr);
1520674ae819SStefano Zampini       if (matstruct == SAME_NONZERO_PATTERN) {
1521e6872a76SStefano Zampini         ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_REUSE_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1522674ae819SStefano Zampini       } else {
1523674ae819SStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
1524e6872a76SStefano Zampini         ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1525e6872a76SStefano Zampini       }
1526674ae819SStefano Zampini     }
152753cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
152853cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
152953cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
153053cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1531da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
15320c7d97c5SJed Brown     /* default */
153353cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
153453cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
15350c7d97c5SJed Brown     /* Allow user's customization */
153653cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1537950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
1538950d796eSStefano Zampini     if (!n_D) {
15392e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1540950d796eSStefano Zampini     }
154153cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
154253cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
15433972b0daSStefano Zampini     /* set ksp_D into pcis data */
15443972b0daSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
15453972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
15463972b0daSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
15470c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
1548534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
154953cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
155053cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
155153cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
155253cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1553da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
15540c7d97c5SJed Brown     /* default */
155553cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
155653cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
15570c7d97c5SJed Brown     /* Allow user's customization */
155853cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1559950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
1560674ae819SStefano Zampini     if (!n_R) {
15612e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1562950d796eSStefano Zampini     }
156353cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
156453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1565674ae819SStefano Zampini     /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
1566b76ba322SStefano Zampini     {
15670c7d97c5SJed Brown       Vec         temp_vec;
1568b76ba322SStefano Zampini       PetscReal   value;
1569e6872a76SStefano Zampini       PetscInt    use_exact,use_exact_reduced;
15700c7d97c5SJed Brown 
1571a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
15720298fd71SBarry Smith       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
1573a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1574a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1575a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1576a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
157729622bf0SStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1578b76ba322SStefano Zampini       use_exact = 1;
15792fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1580ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1581e6872a76SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,(PetscBool)use_exact_reduced);CHKERRQ(ierr);
1582b76ba322SStefano Zampini       if (dbg_flag) {
1583a0ba757dSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1584a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1585a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1586a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1587674ae819SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
158829622bf0SStefano Zampini       }
1589674ae819SStefano Zampini       if (n_D && pcbddc->NullSpace && !use_exact_reduced && !pcbddc->inexact_prec_type) {
1590674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);
159129622bf0SStefano Zampini       }
1592d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
15930298fd71SBarry Smith       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
1594d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1595d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1596d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1597d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1598e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
159929622bf0SStefano Zampini       use_exact = 1;
16002fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1601ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
160229622bf0SStefano Zampini       if (dbg_flag) {
16030c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1604d49ef151SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
16050c7d97c5SJed Brown       }
1606e6872a76SStefano Zampini       if (n_R && pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
1607674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,is_R_local);
160829622bf0SStefano Zampini       }
1609b76ba322SStefano Zampini     }
16100c7d97c5SJed Brown     /* free Neumann problem's matrix */
16110c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
16120c7d97c5SJed Brown   }
16130c7d97c5SJed Brown 
16140c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
16150c7d97c5SJed Brown   {
16160c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
16170bdf917eSStefano Zampini     Mat          M1;
16180c7d97c5SJed Brown     Mat          C_CR;
16193b03a366Sstefano_zampini     Mat          AUXMAT;
16200c7d97c5SJed Brown     Vec          vec1_C;
16210c7d97c5SJed Brown     Vec          vec2_C;
16220c7d97c5SJed Brown     Vec          vec1_V;
16230c7d97c5SJed Brown     Vec          vec2_V;
1624e6872a76SStefano Zampini     IS           is_C_local,is_V_local,is_aux1;
1625e6872a76SStefano Zampini     ISLocalToGlobalMapping BtoNmap;
16260c7d97c5SJed Brown     PetscInt     *nnz;
1627e6872a76SStefano Zampini     PetscInt     *idx_V_B;
16280c7d97c5SJed Brown     PetscInt     *auxindices;
162953cdbc3dSStefano Zampini     PetscInt     index;
16300c7d97c5SJed Brown     PetscScalar* array2;
16310c7d97c5SJed Brown     MatFactorInfo matinfo;
163215aaf578SStefano Zampini     PetscBool    setsym=PETSC_FALSE,issym=PETSC_FALSE;
16330c7d97c5SJed Brown 
16340c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
16350c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
16360c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
16372fa5cd67SKarl Rupp     for (i=0;i<pcis->n;i++) auxindices[i]=i;
16380c7d97c5SJed Brown 
1639e6872a76SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1640e6872a76SStefano Zampini     /* vertices in boundary numbering */
1641e6872a76SStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1642e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
1643e6872a76SStefano Zampini     ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
1644e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
1645e6872a76SStefano Zampini     if (i != n_vertices) {
1646e6872a76SStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1647e6872a76SStefano Zampini     }
1648e6872a76SStefano Zampini 
16490c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
16503b03a366Sstefano_zampini     if (n_vertices) {
16510c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
16523b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
16530c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
16540c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
16550c7d97c5SJed Brown     }
1656534831adSStefano Zampini     if (n_constraints) {
16570c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
1658534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
16590c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
16600c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
16610c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
16620c7d97c5SJed Brown     }
16630c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
16643b03a366Sstefano_zampini     if (n_constraints) {
16650c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
16663b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
16670c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
16680298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,NULL);CHKERRQ(ierr);
16690c7d97c5SJed Brown 
167057a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
1671e6872a76SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
167257a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
167357a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
167457a90decSStefano Zampini 
16750c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
16763b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
16773b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
16783b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
167957a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
168057a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
16812fa5cd67SKarl Rupp         for (j=0;j<size_of_constraint;j++) array[row_cmat_indices[j]] = -row_cmat_values[j];
168257a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
168357a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
16842fa5cd67SKarl Rupp 
16853b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
168653cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
16872fa5cd67SKarl Rupp 
16883b03a366Sstefano_zampini         /* Set values */
16890c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
16903b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
16910c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
16920c7d97c5SJed Brown       }
16930c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16940c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16950c7d97c5SJed Brown 
16960c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
16970c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1698d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
16993b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
17000c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
17010c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
17020c7d97c5SJed Brown 
17033b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1704d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
17053b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
17060c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
17070298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(M1,NULL);CHKERRQ(ierr);
17083b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
17090c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
17100c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
17110c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
17120c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
17130c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
17140c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
17150c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
17163b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17170c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
17180c7d97c5SJed Brown       }
17190c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17200c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17210c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
17220c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
17230c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
17240c7d97c5SJed Brown 
17250c7d97c5SJed Brown     }
17260c7d97c5SJed Brown 
17270c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
17283b03a366Sstefano_zampini     if (n_vertices) {
172915aaf578SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr);
1730534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1731534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1732534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
173315aaf578SStefano Zampini       ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17340c7d97c5SJed Brown     }
17350c7d97c5SJed Brown 
17360c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1737d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
17380c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
17390c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
17400298fd71SBarry Smith     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,NULL);CHKERRQ(ierr);
174129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
1742d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
17430c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
17440c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
17450298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,NULL);CHKERRQ(ierr);
17460c7d97c5SJed Brown     }
17470c7d97c5SJed Brown 
1748e269702eSStefano Zampini     if (dbg_flag) {
17495b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*coarsefunctions_errors),&coarsefunctions_errors);CHKERRQ(ierr);
17505b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*constraints_errors),&constraints_errors);CHKERRQ(ierr);
17510c7d97c5SJed Brown     }
17523b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
17530c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
17540c7d97c5SJed Brown 
17550c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
17563b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++){
17570c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
17580c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
17590c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
17600c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
17610c7d97c5SJed Brown       /* solution of saddle point problem */
17620bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
17630bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17640c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
17653b03a366Sstefano_zampini       if (n_constraints) {
17660c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
17670c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17680c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
17690c7d97c5SJed Brown       }
17700c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
17710c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
17720c7d97c5SJed Brown 
17730c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
17740c7d97c5SJed Brown       /* coarse basis functions */
17750c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
17760c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17770c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17780c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17793b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17800c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17810c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
178229622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag  ) {
17830c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17840c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17850c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17863b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17870c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17880c7d97c5SJed Brown       }
17890c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
17900c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
17912fa5cd67SKarl Rupp       for (j=0; j<n_vertices; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j];   /* WARNING -> column major ordering */
17920c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
17933b03a366Sstefano_zampini       if (n_constraints) {
17940c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
17952fa5cd67SKarl 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 */
17960c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
17970c7d97c5SJed Brown       }
17980c7d97c5SJed Brown 
1799e269702eSStefano Zampini       if ( dbg_flag ) {
18000c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1801d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18020c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18030c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18042fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
18053b03a366Sstefano_zampini         array[ vertices[i] ] = one;
18060c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18070c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18080c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1809d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
18100c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18110c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18122fa5cd67SKarl Rupp         for (j=0;j<n_vertices;j++) array2[j]=array[j];
18130c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18143b03a366Sstefano_zampini         if (n_constraints) {
18150c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18162fa5cd67SKarl Rupp           for (j=0;j<n_constraints;j++) array2[j+n_vertices]=array[j];
18170c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18180c7d97c5SJed Brown         }
18190c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18200c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
18210c7d97c5SJed Brown         /* check saddle point solution */
1822534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
18233b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
18243b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
18253b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
18260c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18273b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
18280c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18293b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
18300c7d97c5SJed Brown       }
18310c7d97c5SJed Brown     }
18320c7d97c5SJed Brown 
18333b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++){
1834d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
18350c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
18360c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
18370c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
18380c7d97c5SJed Brown       /* solution of saddle point problem */
18390c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
18400c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
18410c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
18423b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
18430c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
18440c7d97c5SJed Brown       /* coarse basis functions */
18453b03a366Sstefano_zampini       index=i+n_vertices;
18460c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
18470c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18480c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18490c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
185053cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18510c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
185229622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
18530c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18540c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18550c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
185653cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18570c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
18580c7d97c5SJed Brown       }
18590c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
18603b03a366Sstefano_zampini       if (n_vertices) {
18610c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18622fa5cd67SKarl Rupp         for (j=0; j<n_vertices; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j]; /* WARNING -> column major ordering */
18630c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18640c7d97c5SJed Brown       }
18650c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18662fa5cd67SKarl 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 */
18670c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18680c7d97c5SJed Brown 
1869e269702eSStefano Zampini       if ( dbg_flag ) {
18700c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
187153cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18720c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18730c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18742fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
18750c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18760c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18770c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
187853cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
18790c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18803b03a366Sstefano_zampini         if ( n_vertices) {
18810c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18822fa5cd67SKarl Rupp           for (j=0;j<n_vertices;j++) array2[j]=-array[j];
18830c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18840c7d97c5SJed Brown         }
18850c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18863b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
18870c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18880c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18893972b0daSStefano Zampini         /* check saddle point solution */
1890534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
18913b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
189253cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
18933b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
18940c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
189553cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
18960c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
189753cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
18980c7d97c5SJed Brown       }
18990c7d97c5SJed Brown     }
19000c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19010c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
190229622bf0SStefano Zampini     if ( pcbddc->inexact_prec_type || dbg_flag ) {
19030c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19040c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19050c7d97c5SJed Brown     }
190615aaf578SStefano Zampini     /* compute other basis functions for non-symmetric problems */
190715aaf578SStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
190815aaf578SStefano Zampini     if ( !setsym || (setsym && !issym) ) {
190915aaf578SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
191015aaf578SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
191115aaf578SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
191215aaf578SStefano Zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_B,NULL);CHKERRQ(ierr);
191315aaf578SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag ) {
191415aaf578SStefano Zampini         ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
191515aaf578SStefano Zampini         ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
191615aaf578SStefano Zampini         ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
191715aaf578SStefano Zampini         ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_D,NULL);CHKERRQ(ierr);
191815aaf578SStefano Zampini       }
191915aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
192015aaf578SStefano Zampini         if (n_constraints) {
192115aaf578SStefano Zampini           ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
192215aaf578SStefano Zampini           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
192315aaf578SStefano Zampini           for (j=0;j<n_constraints;j++) {
192415aaf578SStefano Zampini             array[j]=coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i];
192515aaf578SStefano Zampini           }
192615aaf578SStefano Zampini           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
192715aaf578SStefano Zampini         }
192815aaf578SStefano Zampini         if (i<n_vertices) {
192915aaf578SStefano Zampini           ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
193015aaf578SStefano Zampini           ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
193115aaf578SStefano Zampini           ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
193215aaf578SStefano Zampini           ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
193315aaf578SStefano Zampini           ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
193415aaf578SStefano Zampini           if (n_constraints) {
193515aaf578SStefano Zampini             ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
193615aaf578SStefano Zampini           }
193715aaf578SStefano Zampini         } else {
193815aaf578SStefano Zampini           ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
193915aaf578SStefano Zampini         }
194015aaf578SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
194115aaf578SStefano Zampini         ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
194215aaf578SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
194315aaf578SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
194415aaf578SStefano Zampini         ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
194515aaf578SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
194615aaf578SStefano Zampini         ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
194715aaf578SStefano Zampini         if (i<n_vertices) {
194815aaf578SStefano Zampini           ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
194915aaf578SStefano Zampini         }
195015aaf578SStefano Zampini         if ( pcbddc->inexact_prec_type || dbg_flag  ) {
195115aaf578SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195215aaf578SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195315aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
195415aaf578SStefano Zampini           ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
195515aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
195615aaf578SStefano Zampini         }
195715aaf578SStefano Zampini 
195815aaf578SStefano Zampini         if ( dbg_flag ) {
195915aaf578SStefano Zampini           /* assemble subdomain vector on nodes */
196015aaf578SStefano Zampini           ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
196115aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
196215aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
196315aaf578SStefano Zampini           for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
196415aaf578SStefano Zampini           if (i<n_vertices) array[vertices[i]] = one;
196515aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
196615aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
196715aaf578SStefano Zampini           /* assemble subdomain vector of lagrange multipliers */
196815aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
196915aaf578SStefano Zampini           for (j=0;j<pcbddc->local_primal_size;j++) {
197015aaf578SStefano Zampini             array[j]=-coarse_submat_vals[j*pcbddc->local_primal_size+i];
197115aaf578SStefano Zampini           }
197215aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
197315aaf578SStefano Zampini           /* check saddle point solution */
197415aaf578SStefano Zampini           ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
197515aaf578SStefano Zampini           ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
197615aaf578SStefano Zampini           ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
197715aaf578SStefano Zampini           ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
197815aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
197915aaf578SStefano Zampini           array[i]=array[i]+m_one; /* shift by the identity matrix */
198015aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
198115aaf578SStefano Zampini           ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
198215aaf578SStefano Zampini         }
198315aaf578SStefano Zampini       }
198415aaf578SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
198515aaf578SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
198615aaf578SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
198715aaf578SStefano Zampini         ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
198815aaf578SStefano Zampini         ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
198915aaf578SStefano Zampini       }
199015aaf578SStefano Zampini     }
199115aaf578SStefano Zampini     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
19920c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
199315aaf578SStefano Zampini     /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
199415aaf578SStefano Zampini     /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
19959d2fce94SStefano Zampini     if (dbg_flag) {
19960c7d97c5SJed Brown       Mat         coarse_sub_mat;
19970c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
199815aaf578SStefano Zampini       Mat         coarse_phi_D,coarse_phi_B;
199915aaf578SStefano Zampini       Mat         coarse_psi_D,coarse_psi_B;
200015aaf578SStefano Zampini       Mat         A_II,A_BB,A_IB,A_BI;
200119fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
20025b08dc53SStefano Zampini       PetscReal   real_value;
20030c7d97c5SJed Brown 
2004c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2005c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2006c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2007c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2008c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
2009c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
201015aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
201115aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
201215aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
201315aaf578SStefano Zampini       }
2014c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
20150c7d97c5SJed Brown 
20160c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
20170c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
20180c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
201915aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
202015aaf578SStefano Zampini         ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
202115aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
202215aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
202315aaf578SStefano Zampini         ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
202415aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
202515aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
202615aaf578SStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
202715aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
202815aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
202915aaf578SStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
203015aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
203115aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
203215aaf578SStefano Zampini       } else {
203353cdbc3dSStefano Zampini         ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
203453cdbc3dSStefano Zampini         ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
203553cdbc3dSStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
2036c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
203753cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
203853cdbc3dSStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
2039c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
204053cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
204115aaf578SStefano Zampini       }
204253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
204353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
204453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
204515aaf578SStefano Zampini       ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
204615aaf578SStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
20475b08dc53SStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
20480c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
20490c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
20505b08dc53SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
205115aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
205215aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
205315aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
205415aaf578SStefano Zampini       }
205515aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
205615aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
205715aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
205815aaf578SStefano Zampini       }
205915aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
206015aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
206115aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
206215aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
206315aaf578SStefano Zampini         }
206415aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
206515aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
206615aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
206715aaf578SStefano Zampini         }
206815aaf578SStefano Zampini       }
20690c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
207053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
207153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
207253cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
207353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
207453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
207553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
207653cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
207753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
207853cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
207953cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
208015aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
208115aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
208215aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
208315aaf578SStefano Zampini       }
208415aaf578SStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
20850c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
20860c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
20870c7d97c5SJed Brown     }
20880c7d97c5SJed Brown     /* free memory */
20893b03a366Sstefano_zampini     if (n_vertices) {
209015aaf578SStefano Zampini       ierr = PetscFree(vertices);CHKERRQ(ierr);
20910c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
20920c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
20930c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
20940c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
20950c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
20960c7d97c5SJed Brown     }
2097534831adSStefano Zampini     if (n_constraints) {
20980c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
20990c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
21000c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
21010c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
21020c7d97c5SJed Brown     }
2103a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
2104a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2105a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
2106674ae819SStefano Zampini     ierr = PCBDDCSetUpCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
2107a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
21080c7d97c5SJed Brown   }
21090c7d97c5SJed Brown   /* free memory */
21100c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
2111674ae819SStefano Zampini 
21120c7d97c5SJed Brown   PetscFunctionReturn(0);
21130c7d97c5SJed Brown }
21140c7d97c5SJed Brown 
21150c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
21160c7d97c5SJed Brown 
21177cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
21187cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
21197cbb387bSStefano Zampini #include "metis.h"
21207cbb387bSStefano Zampini #define MetisInt    idx_t
21217cbb387bSStefano Zampini #define MetisScalar real_t
21227cbb387bSStefano Zampini #endif
21237cbb387bSStefano Zampini 
21240c7d97c5SJed Brown #undef __FUNCT__
2125674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
2126674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
21270c7d97c5SJed Brown {
2128674ae819SStefano Zampini 
2129674ae819SStefano Zampini 
21300c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
21310c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
21320c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
2133ce94432eSBarry Smith   MPI_Comm  prec_comm;
21340c7d97c5SJed Brown   MPI_Comm  coarse_comm;
21350c7d97c5SJed Brown 
2136674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
2137674ae819SStefano Zampini 
21380c7d97c5SJed Brown   /* common to all choiches */
21390c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
21400c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
21410c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
21420c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
21430c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
21440c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
21450c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
21460c7d97c5SJed Brown   PetscMPIInt master_proc=0;
21470c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
21480c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
21495b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
21500c7d97c5SJed Brown   PetscMPIInt count_recv=0;
21515b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
21520c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
21530c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
21540c7d97c5SJed Brown   /* some other variables */
21550c7d97c5SJed Brown   PetscErrorCode ierr;
215619fd82e9SBarry Smith   MatType coarse_mat_type;
215719fd82e9SBarry Smith   PCType  coarse_pc_type;
215819fd82e9SBarry Smith   KSPType coarse_ksp_type;
215953cdbc3dSStefano Zampini   PC pc_temp;
21604fad6a16SStefano Zampini   PetscInt i,j,k;
21613b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
2162e269702eSStefano Zampini   /* verbose output viewer */
2163e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
21645b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
2165142dfd88SStefano Zampini 
2166ea7e1babSStefano Zampini   PetscInt      offset,offset2;
2167a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
2168523858cfSStefano Zampini   PetscInt      *dnz,*onz;
2169142dfd88SStefano Zampini 
2170142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
21710c7d97c5SJed Brown 
21720c7d97c5SJed Brown   PetscFunctionBegin;
21734b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
21740c7d97c5SJed Brown   ins_local_primal_indices = 0;
21750c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
21760c7d97c5SJed Brown   localsizes2              = 0;
21770c7d97c5SJed Brown   localdispl2              = 0;
21780c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
21790c7d97c5SJed Brown   coarse_ISLG              = 0;
21800c7d97c5SJed Brown 
218153cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
218253cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
2183142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
2184142dfd88SStefano Zampini 
2185beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
2186beed3852SStefano Zampini   {
2187674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
2188ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
2189ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
2190ef028eecSStefano Zampini 
2191ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
2192beed3852SStefano Zampini 
2193beed3852SStefano Zampini     /* Construct needed data structures for message passing */
2194ffe5efe1SStefano Zampini     j = 0;
2195142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2196ffe5efe1SStefano Zampini       j = size_prec_comm;
2197ffe5efe1SStefano Zampini     }
2198ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
2199ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2200beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
2201142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22025619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
2203ffe5efe1SStefano Zampini     } else {
2204ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
2205ffe5efe1SStefano Zampini     }
2206beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
2207ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
2208beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
2209beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
2210beed3852SStefano Zampini     }
2211beed3852SStefano Zampini 
2212da1bb401SStefano Zampini     /* First let's count coarse dofs.
2213beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
2214beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
2215beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2216ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
2217674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
2218674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
2219674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2220674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
2221674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
2222674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2223ef028eecSStefano Zampini     /* Compute number of coarse dofs */
2224674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
2225ef028eecSStefano Zampini 
2226ef028eecSStefano Zampini     if (dbg_flag) {
22272e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22282e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
22292e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
22302e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
22312e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22322fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
2233beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22342e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2235da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2236da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2237da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2238da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2239da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22402e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
22412e8d2280SStefano Zampini         if (array[i] == 1.0) {
22422e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
22432e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
22442e8d2280SStefano Zampini         }
22452e8d2280SStefano Zampini       }
22462e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22472e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
22485b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
22492e8d2280SStefano Zampini       }
2250da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22512e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2252da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2253da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2254da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
22552e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
22562e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22572e8d2280SStefano Zampini     }
2258142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
22590bdf917eSStefano Zampini   }
22600bdf917eSStefano Zampini 
22612e8d2280SStefano Zampini   if (dbg_flag) {
22627cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
22639d9e44b6SStefano Zampini     if (dbg_flag > 1) {
2264674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
22652e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2266674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2267674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
2268674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
2269674ae819SStefano Zampini       }
22702e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22712e8d2280SStefano Zampini     }
22722e8d2280SStefano Zampini   }
22732e8d2280SStefano Zampini 
2274a929c220SStefano Zampini   im_active = 0;
22752fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
2276a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
22770bdf917eSStefano Zampini 
22780bdf917eSStefano Zampini   /* adapt coarse problem type */
22797cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
22804fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22814fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2282a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
22830bdf917eSStefano Zampini         if (dbg_flag) {
2284a929c220SStefano 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);
22850bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22860bdf917eSStefano Zampini         }
22870bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2288142dfd88SStefano Zampini       }
22894fad6a16SStefano Zampini     } else {
22904fad6a16SStefano Zampini       if (dbg_flag) {
2291a929c220SStefano 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);
22924fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22934fad6a16SStefano Zampini       }
22944fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
22954fad6a16SStefano Zampini     }
22964fad6a16SStefano Zampini   }
22977cbb387bSStefano Zampini #else
22987cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
22997cbb387bSStefano Zampini #endif
2300beed3852SStefano Zampini 
23010c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
23020c7d97c5SJed Brown 
2303da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
23040c7d97c5SJed Brown     {
23057cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
23060c7d97c5SJed Brown       /* we need additional variables */
23070c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
23080c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
23090c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
23100c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
23110c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
23120c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
23130c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
23140c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
23150c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
23160c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
23170c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
23180c7d97c5SJed Brown       MetisInt    *faces_adjncy;
23190c7d97c5SJed Brown       MetisInt    *faces_xadj;
23200c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
23210c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
23220c7d97c5SJed Brown       PetscInt    *array_int;
23230c7d97c5SJed Brown       PetscMPIInt my_faces=0;
23240c7d97c5SJed Brown       PetscMPIInt total_faces=0;
23253828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
23260c7d97c5SJed Brown 
23270c7d97c5SJed Brown       /* define some quantities */
23280c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
23290c7d97c5SJed Brown       coarse_mat_type = MATIS;
23300c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
2331142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
23320c7d97c5SJed Brown 
23330c7d97c5SJed Brown       /* details of coarse decomposition */
2334a929c220SStefano Zampini       n_subdomains = active_procs;
23350c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2336a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
23373828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
23383828260eSStefano Zampini 
2339a929c220SStefano Zampini #if 0
2340a929c220SStefano Zampini       PetscMPIInt *old_ranks;
2341a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2342a929c220SStefano Zampini       MatPartitioning mat_part;
2343a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2344a929c220SStefano Zampini       PetscViewer viewer_test;
2345a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
2346a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
2347a929c220SStefano Zampini       Mat         mat_adj;
2348a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2349a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2350a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2351a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2352a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2353a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2354a929c220SStefano Zampini       if (im_active) {
2355a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2356a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2357a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2358a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2359a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2360674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2361674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2362a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2363a929c220SStefano Zampini         k = pcis->n_neigh-1;
2364a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2365a929c220SStefano Zampini         ii[0]=0;
2366a929c220SStefano Zampini         ii[1]=k;
2367a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2368674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2369a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
23700298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2371a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2372a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2373a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2374a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2375a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2376a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2377a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2378a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2379a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2380a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2381a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2382a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2383a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2384a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2385a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2386a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2387a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2388a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2389a929c220SStefano Zampini       }
2390a929c220SStefano Zampini #endif
2391a929c220SStefano Zampini 
23924fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
23930c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
23943828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
23950c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
23960c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
23970c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
23980c7d97c5SJed Brown         }
23990c7d97c5SJed Brown       }
24000c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
24010c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
24027cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
24030c7d97c5SJed Brown             my_faces++;
24040c7d97c5SJed Brown             break;
24050c7d97c5SJed Brown           }
24060c7d97c5SJed Brown         }
24070c7d97c5SJed Brown       }
24080c7d97c5SJed Brown 
240953cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
24100c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
24110c7d97c5SJed Brown       my_faces=0;
24120c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
24130c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
24147cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
24150c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
24160c7d97c5SJed Brown             my_faces++;
24170c7d97c5SJed Brown             break;
24180c7d97c5SJed Brown           }
24190c7d97c5SJed Brown         }
24200c7d97c5SJed Brown       }
24210c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24220c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
24230c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
24240c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
24250c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
24260c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
24270c7d97c5SJed Brown       }
242853cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
24290c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24300c7d97c5SJed Brown         faces_xadj[0]=0;
24310c7d97c5SJed Brown         faces_displacements[0]=0;
24320c7d97c5SJed Brown         j=0;
24330c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
24340c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
24350c7d97c5SJed Brown           if (number_of_faces[i-1]) {
24360c7d97c5SJed Brown             j++;
24370c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
24380c7d97c5SJed Brown           }
24390c7d97c5SJed Brown         }
24400c7d97c5SJed Brown       }
244153cdbc3dSStefano 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);
24420c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
24430c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
24440c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24453828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
24460c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
24470c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
24480c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
24490c7d97c5SJed Brown       }
24500c7d97c5SJed Brown 
24510c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
2452674ae819SStefano Zampini 
24533828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
2454674ae819SStefano Zampini 
24550c7d97c5SJed Brown         ncon=1;
24560c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
24570c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
24580c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
24590c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
24600c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
24610c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
24620c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
24634fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
24643828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
24653828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
24663828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
24670c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2468674ae819SStefano 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);
24693828260eSStefano Zampini           } else {
24703828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2471674ae819SStefano 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);
24723828260eSStefano Zampini           }
24734fad6a16SStefano Zampini         } else {
24742fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
24754fad6a16SStefano Zampini         }
24760c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
24770c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
24780bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
24792fa5cd67SKarl Rupp 
24800c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
24812fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
24822fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
24830c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
24840c7d97c5SJed Brown       }
24850c7d97c5SJed Brown 
24860c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
24870c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2488da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2489da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
24900c7d97c5SJed Brown       }
2491da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2492da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
249353cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
24940c7d97c5SJed Brown 
24950c7d97c5SJed Brown       if ( coarse_color == 0 ) {
249653cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
249753cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
24980c7d97c5SJed Brown       } else {
24990c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
25000c7d97c5SJed Brown       }
25010c7d97c5SJed Brown 
25027cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
25030c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
25040c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
25050bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
25060bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
25070c7d97c5SJed Brown         /* some initializations */
25080c7d97c5SJed Brown         displacements_recv[0]=0;
25090bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
25100c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
25110bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
25120bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
25132fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
25140bdf917eSStefano Zampini           }
25150bdf917eSStefano Zampini         }
25160c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
25172fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
25182fa5cd67SKarl Rupp 
25190c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
25200c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
25210c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
25223828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
25230c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
25240c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
25253828260eSStefano Zampini               total_count_recv[j]+=1;
25260c7d97c5SJed Brown             }
25270c7d97c5SJed Brown           }
25280c7d97c5SJed Brown         }
2529da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
25303828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
25313828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
25323828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
25333828260eSStefano Zampini           }
25343828260eSStefano Zampini           printf("\n");
2535da1bb401SStefano Zampini         }*/
25360c7d97c5SJed Brown 
25370c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
25380bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
25390bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
25400bdf917eSStefano Zampini         }
2541da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2542674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
25433828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
25443828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
25453828260eSStefano Zampini           } else {
25463828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
25473828260eSStefano Zampini           }
2548da1bb401SStefano Zampini         printf("\n");*/
25490c7d97c5SJed Brown       }
25500c7d97c5SJed Brown 
25510c7d97c5SJed Brown       /* Scatter new decomposition for send details */
255253cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
25530c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
25540c7d97c5SJed Brown       if ( coarse_color == 0) {
255553cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
25560c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
255753cdbc3dSStefano 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);
25580c7d97c5SJed Brown       }
25590c7d97c5SJed Brown 
2560da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2561da1bb401SStefano Zampini       if (coarse_color == 0) {
2562da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2563da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
2564da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2565da1bb401SStefano Zampini         printf("\n");
2566da1bb401SStefano Zampini       }*/
25670c7d97c5SJed Brown 
25680c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
25690bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2570da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
25710bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
25720c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
25730c7d97c5SJed Brown       }
25747cbb387bSStefano Zampini #endif
25750c7d97c5SJed Brown       break;
25760c7d97c5SJed Brown     }
25770c7d97c5SJed Brown 
25780c7d97c5SJed Brown     case(REPLICATED_BDDC):
25790c7d97c5SJed Brown 
25800c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
25810c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
25820c7d97c5SJed Brown       coarse_pc_type  = PCLU;
258353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
25840c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
25850c7d97c5SJed Brown       active_rank = rank_prec_comm;
25860c7d97c5SJed Brown       break;
25870c7d97c5SJed Brown 
25880c7d97c5SJed Brown     case(PARALLEL_BDDC):
25890c7d97c5SJed Brown 
25900c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2591674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
25920c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
259353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
25940c7d97c5SJed Brown       coarse_comm = prec_comm;
25950c7d97c5SJed Brown       active_rank = rank_prec_comm;
25960c7d97c5SJed Brown       break;
25970c7d97c5SJed Brown 
25980c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
25990c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
2600674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
26010c7d97c5SJed Brown       coarse_pc_type = PCLU;
260253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
26030c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
26040c7d97c5SJed Brown       active_rank = master_proc;
26050c7d97c5SJed Brown       break;
26060c7d97c5SJed Brown   }
26070c7d97c5SJed Brown 
26080c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
26090c7d97c5SJed Brown 
26100c7d97c5SJed Brown     case(SCATTERS_BDDC):
26110c7d97c5SJed Brown       {
26120c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
26130c7d97c5SJed Brown 
26142e8d2280SStefano Zampini           IS coarse_IS;
26152e8d2280SStefano Zampini 
2616523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2617523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2618523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
2619523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2620523858cfSStefano Zampini             /* nonzeros */
2621523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2622523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2623523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2624523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
2625523858cfSStefano Zampini             }
2626523858cfSStefano Zampini           } else {
26270c7d97c5SJed Brown             PetscMPIInt send_size;
2628ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
26290c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
26300c7d97c5SJed Brown             PetscInt    ii,jj;
26310c7d97c5SJed Brown             MPI_Request *requests;
2632ef028eecSStefano Zampini 
2633523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2634523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
2635523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
2636523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2637523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
2638523858cfSStefano Zampini             j = 0;
2639523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2640523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
2641523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
2642523858cfSStefano Zampini             }
2643523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
2644523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
26450c7d97c5SJed Brown             /* allocate auxiliary space */
2646523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
26470c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
26480c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
26490c7d97c5SJed Brown             /* allocate stuffs for message massing */
26500c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2651523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2652523858cfSStefano Zampini             /* send indices to be inserted */
2653523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2654523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
2655523858cfSStefano 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);
2656523858cfSStefano Zampini             }
2657523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2658523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
2659ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2660ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
2661ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
2662ef028eecSStefano Zampini               }
2663ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2664523858cfSStefano Zampini             }
2665523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2666ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2667ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2668ef028eecSStefano Zampini             }
26690c7d97c5SJed Brown             j = 0;
26700c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
26712e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
26722e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
26730c7d97c5SJed Brown               localdispl2[i] = j;
26740c7d97c5SJed Brown               j += localsizes2[i];
2675523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
26764fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
26772e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
26784fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
26790c7d97c5SJed Brown               }
26804fad6a16SStefano Zampini             }
2681523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
26820c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
26830c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
26840c7d97c5SJed Brown             ins_local_primal_size = 0;
2685ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
2686ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
26870c7d97c5SJed Brown                 ins_local_primal_size++;
2688ea7e1babSStefano Zampini               }
2689ea7e1babSStefano Zampini             }
26900c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
26910c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
26920c7d97c5SJed Brown             j = 0;
2693ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
2694ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
26952e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
26962e8d2280SStefano Zampini                 j++;
2697ea7e1babSStefano Zampini               }
2698ea7e1babSStefano Zampini             }
2699523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2700523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2701523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2702523858cfSStefano Zampini             }
2703523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2704523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2705523858cfSStefano 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);
2706523858cfSStefano Zampini             }
2707523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2708523858cfSStefano Zampini             /* nonzeros */
2709523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2710523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
27110c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
27120c7d97c5SJed Brown             j=0;
27130c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
27140c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
27150c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
27160c7d97c5SJed Brown               } else {
27170c7d97c5SJed Brown                 aux_ins_indices[i]=j;
27180c7d97c5SJed Brown                 j++;
27190c7d97c5SJed Brown               }
27200c7d97c5SJed Brown             }
27214fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
2722523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
2723523858cfSStefano Zampini               for (k=0;k<j;k++) {
2724523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
27250c7d97c5SJed Brown               }
27260c7d97c5SJed Brown             }
2727523858cfSStefano Zampini             /* check */
2728523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2729523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2730523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
27310c7d97c5SJed Brown               }
27320c7d97c5SJed Brown             }
27330c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
27340c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
27350c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
27364fad6a16SStefano Zampini           }
27370c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
2738142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
27390c7d97c5SJed Brown           coarse_comm = prec_comm;
27400c7d97c5SJed Brown           active_rank = rank_prec_comm;
27410c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
27420c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
27430c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
27442e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
27450c7d97c5SJed Brown           /* arrays for values insertion */
27460c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
27472e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
27480c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
27490c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
27500c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
27514fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
27524fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
27534fad6a16SStefano Zampini             }
27540c7d97c5SJed Brown           }
27550c7d97c5SJed Brown         }
27560c7d97c5SJed Brown         break;
2757674ae819SStefano Zampini 
27580c7d97c5SJed Brown     }
27590c7d97c5SJed Brown 
27600c7d97c5SJed Brown     case(GATHERS_BDDC):
27610c7d97c5SJed Brown       {
2762674ae819SStefano Zampini 
27630c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
2764ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
27650c7d97c5SJed Brown 
27660c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
27670c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
27680bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
27690c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
27700c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
27710c7d97c5SJed Brown           /* arrays for values insertion */
27722fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
27730c7d97c5SJed Brown           localdispl2[0]=0;
27742fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
27750c7d97c5SJed Brown           j=0;
27762fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
27770c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
27780c7d97c5SJed Brown         }
27790c7d97c5SJed Brown 
27800c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
27810c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2782ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
27832fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
27842fa5cd67SKarl Rupp 
27850c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2786ef028eecSStefano 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);
278753cdbc3dSStefano 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);
27880c7d97c5SJed Brown         } else {
2789ef028eecSStefano 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);
279053cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
27910c7d97c5SJed Brown         }
2792ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
27930c7d97c5SJed Brown         break;
2794da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
27950c7d97c5SJed Brown   }
27960c7d97c5SJed Brown 
27970c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
27980c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2799142dfd88SStefano Zampini 
2800142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2801142dfd88SStefano Zampini 
28020c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
28030c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
28040c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
28050c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2806674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2807674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
28083b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2809da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
28103b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
28110c7d97c5SJed Brown     } else {
28124fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
28133b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
28140c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2815674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2816674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
28173b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2818da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2819a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
28200c7d97c5SJed Brown     }
2821142dfd88SStefano Zampini     /* preallocation */
2822142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2823ef028eecSStefano Zampini 
2824674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2825ef028eecSStefano Zampini 
2826142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2827142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2828674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2829ef028eecSStefano Zampini 
2830142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2831ef028eecSStefano Zampini 
2832ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2833ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2834ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2835ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2836ef028eecSStefano Zampini 
2837ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2838674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2839ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2840ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2841ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2842ef028eecSStefano Zampini 
2843ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2844ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2845ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2846ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2847ef028eecSStefano Zampini 
2848ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2849ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2850142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2851ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2852ef028eecSStefano Zampini             row_ownership[j]=i;
2853142dfd88SStefano Zampini           }
2854142dfd88SStefano Zampini         }
2855ef028eecSStefano Zampini 
2856ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2857ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2858ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2859ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2860ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2861ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2862ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2863ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2864142dfd88SStefano Zampini             } else {
2865ef028eecSStefano Zampini               my_onz[i] += 1.0;
2866142dfd88SStefano Zampini             }
2867ef028eecSStefano Zampini             if (i != j) {
2868ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2869ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2870ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2871142dfd88SStefano Zampini               } else {
2872ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2873142dfd88SStefano Zampini               }
2874142dfd88SStefano Zampini             }
2875142dfd88SStefano Zampini           }
2876142dfd88SStefano Zampini         }
2877ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2878ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2879a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2880ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2881ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2882a929c220SStefano Zampini         }
2883ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2884ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2885ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2886ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2887ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2888ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
28895b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
28902fa5cd67SKarl Rupp 
2891ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2892ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
28935b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
28942fa5cd67SKarl Rupp 
2895ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2896ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2897ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2898ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2899ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2900ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2901142dfd88SStefano Zampini       } else {
2902142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2903142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2904142dfd88SStefano Zampini           offset2=localdispl2[k];
2905142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2906ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2907ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2908ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2909ef028eecSStefano Zampini           }
2910142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2911142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2912142dfd88SStefano Zampini           }
2913ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2914142dfd88SStefano Zampini         }
2915142dfd88SStefano Zampini       }
29162fa5cd67SKarl Rupp 
2917142dfd88SStefano Zampini       /* check */
2918142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
29192fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
29202fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2921142dfd88SStefano Zampini       }
2922d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2923d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2924142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2925142dfd88SStefano Zampini     } else {
2926523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2927523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2928142dfd88SStefano Zampini     }
2929142dfd88SStefano Zampini     /* insert values */
2930523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
29310c7d97c5SJed 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);
2932523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2933523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2934523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2935523858cfSStefano 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);
2936523858cfSStefano Zampini       } else {
2937523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2938523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2939523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2940523858cfSStefano Zampini           offset2 = localdispl2[k];
2941523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2942ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2943ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2944ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2945ef028eecSStefano Zampini           }
2946523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2947523858cfSStefano 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);
2948ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2949523858cfSStefano Zampini         }
2950523858cfSStefano Zampini       }
2951523858cfSStefano Zampini       ins_local_primal_indices = 0;
2952523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2953ea7e1babSStefano Zampini     } else {
2954ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2955ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2956ea7e1babSStefano Zampini         offset2=localdispl2[k];
2957ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2958ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2959ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2960ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2961ef028eecSStefano Zampini         }
2962ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2963ea7e1babSStefano 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);
2964ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2965ea7e1babSStefano Zampini       }
2966ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2967ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2968ea7e1babSStefano Zampini     }
29690c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29700c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2971142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2972142dfd88SStefano Zampini     if (issym) {
2973142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2974142dfd88SStefano Zampini     }
29750c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
29760bdf917eSStefano Zampini   }
29770bdf917eSStefano Zampini 
29780bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
29790bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
29800bdf917eSStefano Zampini      IS local_IS,global_IS;
29810bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
29820bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
29830bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
29840bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
29850bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
29860bdf917eSStefano Zampini   }
29870bdf917eSStefano Zampini 
2988a929c220SStefano Zampini   /* free memory no longer needed */
2989a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2990a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2991a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2992a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2993a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2994a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2995a929c220SStefano Zampini 
2996674ae819SStefano Zampini   /* Compute coarse null space */
2997674ae819SStefano Zampini   CoarseNullSpace = 0;
29980bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2999674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
30000bdf917eSStefano Zampini   }
30010bdf917eSStefano Zampini 
30020bdf917eSStefano Zampini   /* KSP for coarse problem */
30030bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
30042e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
30050bdf917eSStefano Zampini 
300653cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
300753cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
300853cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
30093b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
301053cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
301153cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
301253cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
30130c7d97c5SJed Brown     /* Allow user's customization */
3014da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
30150c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
301653cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
30174fad6a16SStefano Zampini       i = pcbddc->current_level+1;
30184fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
30194fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
30204fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
302153cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
3022674ae819SStefano Zampini       if (CoarseNullSpace) {
3023674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
3024674ae819SStefano Zampini       }
30254fad6a16SStefano Zampini       if (dbg_flag) {
30264fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
30274fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
302853cdbc3dSStefano Zampini       }
3029674ae819SStefano Zampini     } else {
3030674ae819SStefano Zampini       if (CoarseNullSpace) {
3031674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
3032674ae819SStefano Zampini       }
30334fad6a16SStefano Zampini     }
30344fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
303553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
3036142dfd88SStefano Zampini 
30370298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
30382e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
30392e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
30402e8d2280SStefano Zampini     if (j == 1) {
30412e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
30422e8d2280SStefano Zampini       if (isbddc) {
30432e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
30445619798eSStefano Zampini       }
30455619798eSStefano Zampini     }
30460c7d97c5SJed Brown   }
3047a929c220SStefano Zampini   /* Check coarse problem if requested */
3048142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
3049142dfd88SStefano Zampini     KSP check_ksp;
3050142dfd88SStefano Zampini     PC  check_pc;
3051142dfd88SStefano Zampini     Vec check_vec;
3052142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
305319fd82e9SBarry Smith     KSPType check_ksp_type;
30540c7d97c5SJed Brown 
3055142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
3056142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
3057142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
30580bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
3059142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
30602fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
30612fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
3062142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
3063142dfd88SStefano Zampini     } else {
3064142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
3065142dfd88SStefano Zampini     }
3066142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
3067142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
3068142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
3069142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
3070142dfd88SStefano Zampini     /* create random vec */
3071142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
30720298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
3073674ae819SStefano Zampini     if (CoarseNullSpace) {
30741cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
3075674ae819SStefano Zampini     }
3076142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3077142dfd88SStefano Zampini     /* solve coarse problem */
3078142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3079674ae819SStefano Zampini     if (CoarseNullSpace) {
30801cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
3081674ae819SStefano Zampini     }
3082142dfd88SStefano Zampini     /* check coarse problem residual error */
3083142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
3084142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3085142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3086142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
3087142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
3088142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
3089142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3090142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
3091142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
3092142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
3093e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
30943b03a366Sstefano_zampini     }
3095142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
3096142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
3097142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
309853cdbc3dSStefano Zampini   }
3099674ae819SStefano Zampini   if (dbg_flag) {
3100da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3101da1bb401SStefano Zampini   }
3102674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
3103a0ba757dSStefano Zampini 
31040c7d97c5SJed Brown   PetscFunctionReturn(0);
31050c7d97c5SJed Brown }
31060c7d97c5SJed Brown 
3107