xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 33bc96a4f4522c7e77c48419ee53fa1f761cd021)
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);
455674ae819SStefano Zampini   /* get CSR into graph structure */
456da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
457674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
460674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
461da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4621a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4631a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
464674ae819SStefano Zampini   }
465575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46636e030ebSStefano Zampini   PetscFunctionReturn(0);
46736e030ebSStefano Zampini }
4681e6b0712SBarry Smith 
46936e030ebSStefano Zampini #undef __FUNCT__
470da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
47136e030ebSStefano Zampini /*@
472da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47336e030ebSStefano Zampini 
47436e030ebSStefano Zampini    Not collective
47536e030ebSStefano Zampini 
47636e030ebSStefano Zampini    Input Parameters:
47736e030ebSStefano Zampini +  pc - the preconditioning context
478da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
479da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
480da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
481da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48236e030ebSStefano Zampini 
48336e030ebSStefano Zampini    Level: intermediate
48436e030ebSStefano Zampini 
48536e030ebSStefano Zampini    Notes:
48636e030ebSStefano Zampini 
48736e030ebSStefano Zampini .seealso: PCBDDC
48836e030ebSStefano Zampini @*/
4891a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
49036e030ebSStefano Zampini {
491575ad6abSStefano Zampini   void (*f)(void) = 0;
49236e030ebSStefano Zampini   PetscErrorCode ierr;
49336e030ebSStefano Zampini 
49436e030ebSStefano Zampini   PetscFunctionBegin;
49536e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
496674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
497674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
498674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
499674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
500da1bb401SStefano Zampini   }
50136e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
502575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
503575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
504575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
505575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
506575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50736e030ebSStefano Zampini   }
50836e030ebSStefano Zampini   PetscFunctionReturn(0);
50936e030ebSStefano Zampini }
5109c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5111e6b0712SBarry Smith 
5129c0446d6SStefano Zampini #undef __FUNCT__
5139c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5149c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5159c0446d6SStefano Zampini {
5169c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5179c0446d6SStefano Zampini   PetscInt i;
5189c0446d6SStefano Zampini   PetscErrorCode ierr;
5199c0446d6SStefano Zampini 
5209c0446d6SStefano Zampini   PetscFunctionBegin;
521da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5229c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5239c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5249c0446d6SStefano Zampini   }
525d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
526da1bb401SStefano Zampini   /* allocate space then set */
5279c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5289c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
529da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
530da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5319c0446d6SStefano Zampini   }
5329c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5339c0446d6SStefano Zampini   PetscFunctionReturn(0);
5349c0446d6SStefano Zampini }
5351e6b0712SBarry Smith 
5369c0446d6SStefano Zampini #undef __FUNCT__
5379c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5389c0446d6SStefano Zampini /*@
539da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5409c0446d6SStefano Zampini 
5419c0446d6SStefano Zampini    Not collective
5429c0446d6SStefano Zampini 
5439c0446d6SStefano Zampini    Input Parameters:
5449c0446d6SStefano Zampini +  pc - the preconditioning context
545da1bb401SStefano Zampini -  n - number of index sets defining the fields
546da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5479c0446d6SStefano Zampini 
5489c0446d6SStefano Zampini    Level: intermediate
5499c0446d6SStefano Zampini 
5509c0446d6SStefano Zampini    Notes:
5519c0446d6SStefano Zampini 
5529c0446d6SStefano Zampini .seealso: PCBDDC
5539c0446d6SStefano Zampini @*/
5549c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5559c0446d6SStefano Zampini {
5569c0446d6SStefano Zampini   PetscErrorCode ierr;
5579c0446d6SStefano Zampini 
5589c0446d6SStefano Zampini   PetscFunctionBegin;
5599c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5609c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5619c0446d6SStefano Zampini   PetscFunctionReturn(0);
5629c0446d6SStefano Zampini }
563da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
564534831adSStefano Zampini #undef __FUNCT__
565534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
566534831adSStefano Zampini /* -------------------------------------------------------------------------- */
567534831adSStefano Zampini /*
568534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
569534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5709c0446d6SStefano Zampini 
571534831adSStefano Zampini    Input Parameter:
572534831adSStefano Zampini +  pc - the preconditioner contex
573534831adSStefano Zampini 
574534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
575534831adSStefano Zampini 
576534831adSStefano Zampini    Notes:
577534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
578534831adSStefano Zampini    the user, but instead is called by KSPSolve().
579534831adSStefano Zampini */
580534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
581534831adSStefano Zampini {
582534831adSStefano Zampini   PetscErrorCode ierr;
583534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
584534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
585534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
586534831adSStefano Zampini   Mat            temp_mat;
5873972b0daSStefano Zampini   IS             dirIS;
5883972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5893972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5903972b0daSStefano Zampini   Vec            used_vec;
5913972b0daSStefano Zampini   PetscBool      guess_nonzero;
592534831adSStefano Zampini 
593534831adSStefano Zampini   PetscFunctionBegin;
5943972b0daSStefano Zampini   if (x) {
5953972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
5963972b0daSStefano Zampini     used_vec = x;
5973972b0daSStefano Zampini   } else {
5983972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
5993972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
6003972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6013972b0daSStefano Zampini   }
6023972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6033972b0daSStefano Zampini   if (ksp) {
6043972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6053972b0daSStefano Zampini     if ( !guess_nonzero ) {
6063972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6073972b0daSStefano Zampini     }
6083972b0daSStefano Zampini   }
6093972b0daSStefano Zampini   /* store the original rhs */
6103972b0daSStefano Zampini   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6113972b0daSStefano Zampini 
6123972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
6133972b0daSStefano Zampini   ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6143972b0daSStefano Zampini   ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6153972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6163972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6173972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6183972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6193972b0daSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6203972b0daSStefano Zampini   if (dirIS) {
6213972b0daSStefano Zampini     ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6223972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6233972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6243972b0daSStefano Zampini     ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6252fa5cd67SKarl Rupp     for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6263972b0daSStefano Zampini     ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6273972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6283972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6293972b0daSStefano Zampini   }
6303972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6313972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
632b76ba322SStefano Zampini 
6333972b0daSStefano Zampini   /* remove the computed solution from the rhs */
6343972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6353972b0daSStefano Zampini   ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6363972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
637b76ba322SStefano Zampini 
638b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6393972b0daSStefano Zampini   if (x) {
6403972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6413972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
64215aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
643b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
644b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
645b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
646b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
647b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
648b76ba322SStefano Zampini       if (ksp) {
649b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
650b76ba322SStefano Zampini       }
651b76ba322SStefano Zampini     }
6523972b0daSStefano Zampini   }
653b76ba322SStefano Zampini 
654b76ba322SStefano Zampini   /* rhs change of basis */
655674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
656b76ba322SStefano Zampini     /* swap pointers for local matrices */
657b76ba322SStefano Zampini     temp_mat = matis->A;
658b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
659b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
660b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
661b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
662b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
663b76ba322SStefano Zampini     /* from original basis to modified basis */
664b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
665b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
666b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
667b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
668674ae819SStefano Zampini   }
6690bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
670d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
671d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
672b76ba322SStefano Zampini   }
6730bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
674534831adSStefano Zampini   PetscFunctionReturn(0);
675534831adSStefano Zampini }
676534831adSStefano Zampini /* -------------------------------------------------------------------------- */
677534831adSStefano Zampini #undef __FUNCT__
678534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
679534831adSStefano Zampini /* -------------------------------------------------------------------------- */
680534831adSStefano Zampini /*
681534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
682534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
683534831adSStefano Zampini 
684534831adSStefano Zampini    Input Parameter:
685534831adSStefano Zampini +  pc - the preconditioner contex
686534831adSStefano Zampini 
687534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
688534831adSStefano Zampini 
689534831adSStefano Zampini    Notes:
690534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
691534831adSStefano Zampini    the user, but instead is called by KSPSolve().
692534831adSStefano Zampini */
693534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
694534831adSStefano Zampini {
695534831adSStefano Zampini   PetscErrorCode ierr;
696534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
697534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
698534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
699534831adSStefano Zampini   Mat            temp_mat;
700534831adSStefano Zampini 
701534831adSStefano Zampini   PetscFunctionBegin;
702674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
703534831adSStefano Zampini     /* swap pointers for local matrices */
704534831adSStefano Zampini     temp_mat = matis->A;
705534831adSStefano Zampini     matis->A = pcbddc->local_mat;
706534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
707534831adSStefano Zampini     /* restore rhs to its original state */
7083425bc38SStefano Zampini     if (rhs) {
7093425bc38SStefano Zampini       ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
7103425bc38SStefano Zampini     }
711534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
712534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
713534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
714534831adSStefano Zampini     /* from modified basis to original basis */
715534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
716534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
717534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
718534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
719534831adSStefano Zampini   }
7203972b0daSStefano Zampini   /* add solution removed in presolve */
7213425bc38SStefano Zampini   if (x) {
7223425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7233425bc38SStefano Zampini   }
724534831adSStefano Zampini   PetscFunctionReturn(0);
725534831adSStefano Zampini }
726534831adSStefano Zampini /* -------------------------------------------------------------------------- */
72753cdbc3dSStefano Zampini #undef __FUNCT__
72853cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7290c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7300c7d97c5SJed Brown /*
7310c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7320c7d97c5SJed Brown                   by setting data structures and options.
7330c7d97c5SJed Brown 
7340c7d97c5SJed Brown    Input Parameter:
73553cdbc3dSStefano Zampini +  pc - the preconditioner context
7360c7d97c5SJed Brown 
7370c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7380c7d97c5SJed Brown 
7390c7d97c5SJed Brown    Notes:
7400c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7410c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7420c7d97c5SJed Brown */
74353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7440c7d97c5SJed Brown {
7450c7d97c5SJed Brown   PetscErrorCode ierr;
7460c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
747674ae819SStefano Zampini   MatStructure   flag;
748674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7490c7d97c5SJed Brown 
7500c7d97c5SJed Brown   PetscFunctionBegin;
751674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7523b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7539c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7540c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7550c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7560c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7573b03a366Sstefano_zampini   /* Get stdout for dbg */
758674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
759ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
760e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
761e269702eSStefano Zampini   }
762674ae819SStefano Zampini   /* first attempt to split work */
763674ae819SStefano Zampini   if (pc->setupcalled) {
764674ae819SStefano Zampini     computeis = PETSC_FALSE;
765674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
766674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
767674ae819SStefano Zampini       computetopography = PETSC_FALSE;
768674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
769674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
770674ae819SStefano Zampini       computetopography = PETSC_FALSE;
771674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
772674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
773674ae819SStefano Zampini       computetopography = PETSC_TRUE;
774674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
775674ae819SStefano Zampini     }
776674ae819SStefano Zampini   } else {
777674ae819SStefano Zampini     computeis = PETSC_TRUE;
778674ae819SStefano Zampini     computetopography = PETSC_TRUE;
779674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
780674ae819SStefano Zampini   }
781674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
782674ae819SStefano Zampini   if (computeis) {
783674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
784674ae819SStefano Zampini   }
785674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
786674ae819SStefano Zampini   if (computetopography) {
787674ae819SStefano Zampini     /* reset data */
788674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
789674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
790674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
791674ae819SStefano Zampini   }
792674ae819SStefano Zampini   if (computesolvers) {
793674ae819SStefano Zampini     /* reset data */
794674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
795674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
7960c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
7970c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
798674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
7990c7d97c5SJed Brown   }
8000c7d97c5SJed Brown   PetscFunctionReturn(0);
8010c7d97c5SJed Brown }
8020c7d97c5SJed Brown 
8030c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8040c7d97c5SJed Brown /*
8050c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8060c7d97c5SJed Brown 
8070c7d97c5SJed Brown    Input Parameters:
8080c7d97c5SJed Brown .  pc - the preconditioner context
8090c7d97c5SJed Brown .  r - input vector (global)
8100c7d97c5SJed Brown 
8110c7d97c5SJed Brown    Output Parameter:
8120c7d97c5SJed Brown .  z - output vector (global)
8130c7d97c5SJed Brown 
8140c7d97c5SJed Brown    Application Interface Routine: PCApply()
8150c7d97c5SJed Brown  */
8160c7d97c5SJed Brown #undef __FUNCT__
8170c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
81853cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8190c7d97c5SJed Brown {
8200c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8210c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8220c7d97c5SJed Brown   PetscErrorCode    ierr;
8233b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8243b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8252617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8260c7d97c5SJed Brown 
8270c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8280c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
82929622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8300c7d97c5SJed Brown 
8310c7d97c5SJed Brown   PetscFunctionBegin;
83215aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8330c7d97c5SJed Brown     /* First Dirichlet solve */
8340c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8350c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
83653cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8370c7d97c5SJed Brown     /*
8380c7d97c5SJed Brown       Assembling right hand side for BDDC operator
839674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
840674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8410c7d97c5SJed Brown     */
8420c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8430c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
84429622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8450c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8460c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8470c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8480c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
849674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
850b76ba322SStefano Zampini   } else {
8510bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
852b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
853674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
854b76ba322SStefano Zampini   }
855b76ba322SStefano Zampini 
8562617d88aSStefano Zampini   /* Apply interface preconditioner
8572617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8582617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8592617d88aSStefano Zampini 
860674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
861674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8620c7d97c5SJed Brown 
8633b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8640c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8650c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8660c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
86729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
86853cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8690c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
87029622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8710c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8720c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8730c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8740c7d97c5SJed Brown   PetscFunctionReturn(0);
8750c7d97c5SJed Brown }
876da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
877674ae819SStefano Zampini 
878da1bb401SStefano Zampini #undef __FUNCT__
879da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
880da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
881da1bb401SStefano Zampini {
882da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
883da1bb401SStefano Zampini   PetscErrorCode ierr;
884da1bb401SStefano Zampini 
885da1bb401SStefano Zampini   PetscFunctionBegin;
886da1bb401SStefano Zampini   /* free data created by PCIS */
887da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
888674ae819SStefano Zampini   /* free BDDC custom data  */
889674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
890674ae819SStefano Zampini   /* destroy objects related to topography */
891674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
892674ae819SStefano Zampini   /* free allocated graph structure */
893da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
894674ae819SStefano Zampini   /* free data for scaling operator */
895674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
896674ae819SStefano Zampini   /* free solvers stuff */
897674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
898*33bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
899*33bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
9003425bc38SStefano Zampini   /* remove functions */
901674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
902bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
903bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
904bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
905bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
906bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
907bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
908bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
909bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
910bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
911bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
912bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
913bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
914bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
915674ae819SStefano Zampini   /* Free the private data structure */
916674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
917da1bb401SStefano Zampini   PetscFunctionReturn(0);
918da1bb401SStefano Zampini }
9193425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9201e6b0712SBarry Smith 
9213425bc38SStefano Zampini #undef __FUNCT__
9223425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9233425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9243425bc38SStefano Zampini {
925674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9263425bc38SStefano Zampini   PC_IS*         pcis;
9273425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9283425bc38SStefano Zampini   PetscErrorCode ierr;
9290c7d97c5SJed Brown 
9303425bc38SStefano Zampini   PetscFunctionBegin;
9313425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9323425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9333425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9343425bc38SStefano Zampini 
9353425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9363425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
9370298fd71SBarry Smith   (*mat_ctx->pc->ops->presolve)(mat_ctx->pc,NULL,standard_rhs,NULL);
9383425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9393425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9403425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
941674ae819SStefano Zampini   /* scale rhs since it should be unassembled : TODO use counter scaling? (also below) */
9423425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9433425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
944674ae819SStefano Zampini   /* Apply partition of unity */
9453425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
946674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
94729622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9483425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9493425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9503425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9513425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9523425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9533425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9543425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
955674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9563425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9573425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9583425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9593425bc38SStefano Zampini   }
9603425bc38SStefano Zampini   /* BDDC rhs */
9613425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
96229622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9633425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9643425bc38SStefano Zampini   }
9653425bc38SStefano Zampini   /* apply BDDC */
9663425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9673425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9683425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9693425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9703425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9713425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9723425bc38SStefano Zampini   /* restore original rhs */
9733425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9743425bc38SStefano Zampini   PetscFunctionReturn(0);
9753425bc38SStefano Zampini }
9761e6b0712SBarry Smith 
9773425bc38SStefano Zampini #undef __FUNCT__
9783425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9793425bc38SStefano Zampini /*@
9803425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9813425bc38SStefano Zampini 
9823425bc38SStefano Zampini    Collective
9833425bc38SStefano Zampini 
9843425bc38SStefano Zampini    Input Parameters:
9853425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
9863425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
9873425bc38SStefano Zampini 
9883425bc38SStefano Zampini    Output Parameters:
9893425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
9903425bc38SStefano Zampini 
9913425bc38SStefano Zampini    Level: developer
9923425bc38SStefano Zampini 
9933425bc38SStefano Zampini    Notes:
9943425bc38SStefano Zampini 
9953425bc38SStefano Zampini .seealso: PCBDDC
9963425bc38SStefano Zampini @*/
9973425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9983425bc38SStefano Zampini {
999674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10003425bc38SStefano Zampini   PetscErrorCode ierr;
10013425bc38SStefano Zampini 
10023425bc38SStefano Zampini   PetscFunctionBegin;
10033425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10043425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10053425bc38SStefano Zampini   PetscFunctionReturn(0);
10063425bc38SStefano Zampini }
10073425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10081e6b0712SBarry Smith 
10093425bc38SStefano Zampini #undef __FUNCT__
10103425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10113425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10123425bc38SStefano Zampini {
1013674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10143425bc38SStefano Zampini   PC_IS*         pcis;
10153425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10163425bc38SStefano Zampini   PetscErrorCode ierr;
10173425bc38SStefano Zampini 
10183425bc38SStefano Zampini   PetscFunctionBegin;
10193425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10203425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10213425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10223425bc38SStefano Zampini 
10233425bc38SStefano Zampini   /* apply B_delta^T */
10243425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10253425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10263425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10273425bc38SStefano Zampini   /* compute rhs for BDDC application */
10283425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
102929622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10303425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10313425bc38SStefano Zampini   }
10323425bc38SStefano Zampini   /* apply BDDC */
10333425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10343425bc38SStefano Zampini   /* put values into standard global vector */
10353425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10363425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
103729622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10383425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10393425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10403425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10413425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10423425bc38SStefano Zampini   }
10433425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10443425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10453425bc38SStefano Zampini   /* final change of basis if needed
10463425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10470298fd71SBarry Smith   (*mat_ctx->pc->ops->postsolve)(mat_ctx->pc,NULL,NULL,standard_sol);
10483425bc38SStefano Zampini   PetscFunctionReturn(0);
10493425bc38SStefano Zampini 
10503425bc38SStefano Zampini }
10511e6b0712SBarry Smith 
10523425bc38SStefano Zampini #undef __FUNCT__
10533425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10543425bc38SStefano Zampini /*@
10553425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10563425bc38SStefano Zampini 
10573425bc38SStefano Zampini    Collective
10583425bc38SStefano Zampini 
10593425bc38SStefano Zampini    Input Parameters:
10603425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10613425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10623425bc38SStefano Zampini 
10633425bc38SStefano Zampini    Output Parameters:
10643425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10653425bc38SStefano Zampini 
10663425bc38SStefano Zampini    Level: developer
10673425bc38SStefano Zampini 
10683425bc38SStefano Zampini    Notes:
10693425bc38SStefano Zampini 
10703425bc38SStefano Zampini .seealso: PCBDDC
10713425bc38SStefano Zampini @*/
10723425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10733425bc38SStefano Zampini {
1074674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10753425bc38SStefano Zampini   PetscErrorCode ierr;
10763425bc38SStefano Zampini 
10773425bc38SStefano Zampini   PetscFunctionBegin;
10783425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10793425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10803425bc38SStefano Zampini   PetscFunctionReturn(0);
10813425bc38SStefano Zampini }
10823425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10831e6b0712SBarry Smith 
1084f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1085f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1086f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1087f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1088674ae819SStefano Zampini 
10893425bc38SStefano Zampini #undef __FUNCT__
10903425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
10913425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
10923425bc38SStefano Zampini {
1093674ae819SStefano Zampini 
1094674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
10953425bc38SStefano Zampini   Mat            newmat;
1096674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
10973425bc38SStefano Zampini   PC             newpc;
1098ce94432eSBarry Smith   MPI_Comm       comm;
10993425bc38SStefano Zampini   PetscErrorCode ierr;
11003425bc38SStefano Zampini 
11013425bc38SStefano Zampini   PetscFunctionBegin;
1102ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
11033425bc38SStefano Zampini   /* FETIDP linear matrix */
11043425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11053425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11063425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11073425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11083425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11093425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11103425bc38SStefano Zampini   /* FETIDP preconditioner */
11113425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11123425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11133425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11143425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11153425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11163425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11173425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11183425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11193425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11203425bc38SStefano Zampini   /* return pointers for objects created */
11213425bc38SStefano Zampini   *fetidp_mat=newmat;
11223425bc38SStefano Zampini   *fetidp_pc=newpc;
11233425bc38SStefano Zampini   PetscFunctionReturn(0);
11243425bc38SStefano Zampini }
11251e6b0712SBarry Smith 
11263425bc38SStefano Zampini #undef __FUNCT__
11273425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11283425bc38SStefano Zampini /*@
11293425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11303425bc38SStefano Zampini 
11313425bc38SStefano Zampini    Collective
11323425bc38SStefano Zampini 
11333425bc38SStefano Zampini    Input Parameters:
11343425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11353425bc38SStefano Zampini 
11363425bc38SStefano Zampini    Level: developer
11373425bc38SStefano Zampini 
11383425bc38SStefano Zampini    Notes:
11393425bc38SStefano Zampini 
11403425bc38SStefano Zampini .seealso: PCBDDC
11413425bc38SStefano Zampini @*/
11423425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11433425bc38SStefano Zampini {
11443425bc38SStefano Zampini   PetscErrorCode ierr;
11453425bc38SStefano Zampini 
11463425bc38SStefano Zampini   PetscFunctionBegin;
11473425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11483425bc38SStefano Zampini   if (pc->setupcalled) {
11493425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1150f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11513425bc38SStefano Zampini   PetscFunctionReturn(0);
11523425bc38SStefano Zampini }
11530c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1154da1bb401SStefano Zampini /*MC
1155da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11560c7d97c5SJed Brown 
1157da1bb401SStefano Zampini    Options Database Keys:
1158da1bb401SStefano Zampini .    -pcbddc ??? -
1159da1bb401SStefano Zampini 
1160da1bb401SStefano Zampini    Level: intermediate
1161da1bb401SStefano Zampini 
1162da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1163da1bb401SStefano Zampini 
1164da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1165da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1166da1bb401SStefano Zampini           on the subdomains).
1167da1bb401SStefano Zampini 
1168da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1169da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1170da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1171da1bb401SStefano Zampini 
1172da1bb401SStefano Zampini    Contributed by Stefano Zampini
1173da1bb401SStefano Zampini 
1174da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1175da1bb401SStefano Zampini M*/
1176b2573a8aSBarry Smith 
1177da1bb401SStefano Zampini #undef __FUNCT__
1178da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11798cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1180da1bb401SStefano Zampini {
1181da1bb401SStefano Zampini   PetscErrorCode      ierr;
1182da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1183da1bb401SStefano Zampini 
1184da1bb401SStefano Zampini   PetscFunctionBegin;
1185da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1186da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1187da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1188da1bb401SStefano Zampini 
1189da1bb401SStefano Zampini   /* create PCIS data structure */
1190da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1191da1bb401SStefano Zampini 
1192da1bb401SStefano Zampini   /* BDDC specific */
1193674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
11940bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
11953972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1196534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1197534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1198534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1199674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1200674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1201da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1202da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1203da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1204da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1205da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
120615aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
120715aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
1208da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1209da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1210da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1211da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1212da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1213da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1214da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1215da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1216da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1217da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
121829622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1219da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1220da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1221da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1222da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1223da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1224da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1225da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
12269d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1227da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1228b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12294fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12304fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1231674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1232674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1233da1bb401SStefano Zampini 
1234674ae819SStefano Zampini   /* create local graph structure */
1235674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1236674ae819SStefano Zampini 
1237674ae819SStefano Zampini   /* scaling */
1238674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1239674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1240da1bb401SStefano Zampini 
1241da1bb401SStefano Zampini   /* function pointers */
1242da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1243da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1244da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1245da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1246da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1247da1bb401SStefano Zampini   pc->ops->view                = 0;
1248da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1249da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1250da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1251534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1252534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1253da1bb401SStefano Zampini 
1254da1bb401SStefano Zampini   /* composing function */
1255674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1256bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1257bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1258bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1259bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1260bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1261bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1262bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1263bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1264bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1265bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1266bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1267bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1268bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1269da1bb401SStefano Zampini   PetscFunctionReturn(0);
1270da1bb401SStefano Zampini }
12713425bc38SStefano Zampini 
1272da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1273da1bb401SStefano Zampini /* All static functions from now on                                           */
1274da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
127529622bf0SStefano Zampini 
127629622bf0SStefano Zampini #undef __FUNCT__
12772e8d2280SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
12782e8d2280SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool use)
12792e8d2280SStefano Zampini {
12802e8d2280SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12812e8d2280SStefano Zampini 
12822e8d2280SStefano Zampini   PetscFunctionBegin;
12832e8d2280SStefano Zampini   pcbddc->use_exact_dirichlet=use;
12842e8d2280SStefano Zampini   PetscFunctionReturn(0);
12852e8d2280SStefano Zampini }
12862e8d2280SStefano Zampini 
12872e8d2280SStefano Zampini #undef __FUNCT__
12884fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12894fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12904fad6a16SStefano Zampini {
12914fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12924fad6a16SStefano Zampini 
12934fad6a16SStefano Zampini   PetscFunctionBegin;
12944fad6a16SStefano Zampini   pcbddc->current_level=level;
12954fad6a16SStefano Zampini   PetscFunctionReturn(0);
12964fad6a16SStefano Zampini }
12973425bc38SStefano Zampini 
12983b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
12990c7d97c5SJed Brown #undef __FUNCT__
13000c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
130153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
13020c7d97c5SJed Brown {
13030c7d97c5SJed Brown   PetscErrorCode  ierr;
1304674ae819SStefano Zampini 
13050c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
13060c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
13070c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
13080c7d97c5SJed Brown   IS                is_R_local;
130919fd82e9SBarry Smith   VecType           impVecType;
131019fd82e9SBarry Smith   MatType           impMatType;
13110c7d97c5SJed Brown   PetscInt          n_R=0;
13120c7d97c5SJed Brown   PetscInt          n_D=0;
13130c7d97c5SJed Brown   PetscInt          n_B=0;
13140c7d97c5SJed Brown   PetscScalar       zero=0.0;
13150c7d97c5SJed Brown   PetscScalar       one=1.0;
13160c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
13170c7d97c5SJed Brown   PetscScalar*      array;
13180c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
13190c7d97c5SJed Brown   PetscInt          *idx_R_local;
13205b08dc53SStefano Zampini   PetscReal         *coarsefunctions_errors,*constraints_errors;
13210c7d97c5SJed Brown   /* auxiliary indices */
1322534831adSStefano Zampini   PetscInt          i,j,k;
1323e269702eSStefano Zampini   /* for verbose output of bddc */
1324e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
13255b08dc53SStefano Zampini   PetscInt          dbg_flag=pcbddc->dbg_flag;
1326a0ba757dSStefano Zampini   /* for counting coarse dofs */
1327534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
13283b03a366Sstefano_zampini   PetscInt          size_of_constraint;
13293b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
13303b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1331e6872a76SStefano Zampini   PetscInt          *vertices;
13320c7d97c5SJed Brown 
13330c7d97c5SJed Brown   PetscFunctionBegin;
13340c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
13350c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
1336534831adSStefano Zampini 
1337534831adSStefano Zampini   /* transform local matrices if needed */
1338674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
1339e6872a76SStefano Zampini     Mat      change_mat_all;
1340e6872a76SStefano Zampini     PetscInt *nnz,*is_indices,*temp_indices;
1341e6872a76SStefano Zampini 
1342534831adSStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1343534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13442fa5cd67SKarl Rupp     for (i=0;i<n_D;i++) nnz[is_indices[i]] = 1;
1345534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1346534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1347534831adSStefano Zampini     k=1;
1348534831adSStefano Zampini     for (i=0;i<n_B;i++) {
13490298fd71SBarry Smith       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1350534831adSStefano Zampini       nnz[is_indices[i]]=j;
13512fa5cd67SKarl Rupp       if (k < j) k = j;
13520298fd71SBarry Smith       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
1353534831adSStefano Zampini     }
1354534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1355534831adSStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
1356534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
1357534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
1358534831adSStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
1359534831adSStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
1360534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
1361534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1362534831adSStefano Zampini     for (i=0;i<n_D;i++) {
1363534831adSStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
1364534831adSStefano Zampini     }
1365534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1366534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1367534831adSStefano Zampini     for (i=0;i<n_B;i++) {
1368534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
13692fa5cd67SKarl Rupp       for (k=0; k<j; k++) temp_indices[k]=is_indices[row_cmat_indices[k]];
1370534831adSStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
1371534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
1372534831adSStefano Zampini     }
1373534831adSStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1374534831adSStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13755ce978abSStefano Zampini     /* TODO: HOW TO WORK WITH BAIJ? PtAP not provided */
13765ce978abSStefano Zampini     ierr = MatGetBlockSize(matis->A,&i);CHKERRQ(ierr);
13775ce978abSStefano Zampini     if (i==1) {
1378534831adSStefano Zampini       ierr = MatPtAP(matis->A,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13795ce978abSStefano Zampini     } else {
13805ce978abSStefano Zampini       Mat work_mat;
13815ce978abSStefano Zampini       ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
13825ce978abSStefano Zampini       ierr = MatPtAP(work_mat,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
13835ce978abSStefano Zampini       ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
13845ce978abSStefano Zampini     }
1385534831adSStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
1386534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1387534831adSStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
1388534831adSStefano Zampini   } else {
1389534831adSStefano Zampini     /* without change of basis, the local matrix is unchanged */
1390534831adSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1391534831adSStefano Zampini     pcbddc->local_mat = matis->A;
1392534831adSStefano Zampini   }
139315aaf578SStefano Zampini   /* need to rebuild PCIS matrices during SNES or TS -> TODO move this to PCIS code */
139415aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
139515aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
139615aaf578SStefano Zampini   ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
139715aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
139815aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
139915aaf578SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
1400674ae819SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1401674ae819SStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1402674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
14030bdf917eSStefano Zampini   }
1404a0ba757dSStefano Zampini 
1405e6872a76SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
1406e6872a76SStefano Zampini   impMatType = MATSEQDENSE;
1407e6872a76SStefano Zampini   impVecType = VECSEQ;
1408e6872a76SStefano Zampini   /* get vertex indices from constraint matrix */
1409e6872a76SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1410e6872a76SStefano Zampini   /* Set number of constraints */
1411e6872a76SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
14120c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
14130c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
14140c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14152fa5cd67SKarl Rupp   for (i=0;i<n_vertices;i++) array[vertices[i]] = zero;
14163b03a366Sstefano_zampini   ierr = PetscMalloc((pcis->n-n_vertices)*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
14172fa5cd67SKarl Rupp   for (i=0, n_R=0; i<pcis->n; i++) {
14182fa5cd67SKarl Rupp     if (array[i] == one) {
14192fa5cd67SKarl Rupp       idx_R_local[n_R] = i;
14202fa5cd67SKarl Rupp       n_R++;
14212fa5cd67SKarl Rupp     }
14222fa5cd67SKarl Rupp   }
14230c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1424e6872a76SStefano Zampini   ierr = PetscFree(vertices);CHKERRQ(ierr);
1425e269702eSStefano Zampini   if (dbg_flag) {
14260c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14270c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14280c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
14290c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
14303b03a366Sstefano_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);
1431534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
14320c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14330c7d97c5SJed Brown   }
1434534831adSStefano Zampini 
14350c7d97c5SJed Brown   /* Allocate needed vectors */
1436534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
14373972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
14380c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
14390c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
14400c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
14410c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1442d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
14430c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
14440c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
14450c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
14460c7d97c5SJed Brown 
14470c7d97c5SJed Brown   /* Creating some index sets needed  */
14480c7d97c5SJed Brown   /* For submatrices */
1449da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
1450da1bb401SStefano Zampini 
14510c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
14520c7d97c5SJed Brown   {
1453e6872a76SStefano Zampini     IS         is_aux1,is_aux2;
14540c7d97c5SJed Brown     PetscInt   *aux_array1;
14550c7d97c5SJed Brown     PetscInt   *aux_array2;
14562e8d2280SStefano Zampini     PetscInt   *idx_I_local;
14570c7d97c5SJed Brown 
14583b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14593b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
14600c7d97c5SJed Brown 
14612e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14620c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14632fa5cd67SKarl Rupp     for (i=0; i<n_D; i++) array[idx_I_local[i]] = 0;
14642e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
14652fa5cd67SKarl Rupp     for (i=0, j=0; i<n_R; i++) {
14662fa5cd67SKarl Rupp       if (array[idx_R_local[i]] == one) {
14672fa5cd67SKarl Rupp         aux_array1[j] = i;
14682fa5cd67SKarl Rupp         j++;
14692fa5cd67SKarl Rupp       }
14702fa5cd67SKarl Rupp     }
14710c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1472da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
14732e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14742e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14750c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
14762fa5cd67SKarl Rupp     for (i=0, j=0; i<n_B; i++) {
14772fa5cd67SKarl Rupp       if (array[i] == one) {
14782fa5cd67SKarl Rupp         aux_array2[j] = i; j++;
14792fa5cd67SKarl Rupp       }
14802fa5cd67SKarl Rupp     }
14813828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1482da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
14830c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
14840c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
14850c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
14860c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14870c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
14880c7d97c5SJed Brown 
148929622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
14900c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14910c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14922fa5cd67SKarl Rupp       for (i=0, j=0; i<n_R; i++) {
14932fa5cd67SKarl Rupp         if (array[idx_R_local[i]] == zero) {
14942fa5cd67SKarl Rupp           aux_array1[j] = i;
14952fa5cd67SKarl Rupp           j++;
14962fa5cd67SKarl Rupp         }
14972fa5cd67SKarl Rupp       }
14980c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1499da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
15000c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
15010c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
15020c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
15030c7d97c5SJed Brown     }
15040c7d97c5SJed Brown   }
15050c7d97c5SJed Brown 
15060c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
15070c7d97c5SJed Brown   {
15080c7d97c5SJed Brown     Mat          A_RR;
150953cdbc3dSStefano Zampini     PC           pc_temp;
1510674ae819SStefano Zampini     MatStructure matstruct;
1511*33bc96a4SStefano Zampini 
1512674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&matstruct);CHKERRQ(ierr);
1513*33bc96a4SStefano Zampini 
1514*33bc96a4SStefano Zampini     /* DIRICHLET PROBLEM */
1515*33bc96a4SStefano Zampini     /* Matrix for Dirichlet problem is A_II */
1516*33bc96a4SStefano Zampini     /* HACK: A_II can be changed between nonlinear iterations */
1517*33bc96a4SStefano Zampini     if (pc->setupcalled) { /* we dont need to rebuild dirichlet problem the first time we build BDDC */
1518674ae819SStefano Zampini       if (matstruct == SAME_NONZERO_PATTERN) {
1519e6872a76SStefano Zampini         ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_REUSE_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1520674ae819SStefano Zampini       } else {
1521674ae819SStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
1522e6872a76SStefano Zampini         ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr);
1523e6872a76SStefano Zampini       }
1524674ae819SStefano Zampini     }
1525*33bc96a4SStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
152653cdbc3dSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
152753cdbc3dSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1528*33bc96a4SStefano Zampini       /* default */
152953cdbc3dSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1530da1bb401SStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
153153cdbc3dSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
153253cdbc3dSStefano Zampini       ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
1533*33bc96a4SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1534*33bc96a4SStefano Zampini     }
1535*33bc96a4SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,matstruct);CHKERRQ(ierr);
15360c7d97c5SJed Brown     /* Allow user's customization */
153753cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1538*33bc96a4SStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1539950d796eSStefano Zampini     if (!n_D) {
1540*33bc96a4SStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
15412e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1542950d796eSStefano Zampini     }
154353cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
154453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
15453972b0daSStefano Zampini     /* set ksp_D into pcis data */
15463972b0daSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
15473972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
15483972b0daSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1549*33bc96a4SStefano Zampini 
1550*33bc96a4SStefano Zampini     /* NEUMANN PROBLEM */
15510c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
1552534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
1553*33bc96a4SStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not yet build */
155453cdbc3dSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
155553cdbc3dSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1556*33bc96a4SStefano Zampini       /* default */
155753cdbc3dSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1558da1bb401SStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
155953cdbc3dSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
156053cdbc3dSStefano Zampini       ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
1561*33bc96a4SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1562*33bc96a4SStefano Zampini     }
1563*33bc96a4SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,matstruct);CHKERRQ(ierr);
15640c7d97c5SJed Brown     /* Allow user's customization */
156553cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1566*33bc96a4SStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1567674ae819SStefano Zampini     if (!n_R) {
1568*33bc96a4SStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
15692e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1570950d796eSStefano Zampini     }
157153cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
157253cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1573*33bc96a4SStefano Zampini 
1574674ae819SStefano Zampini     /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
1575b76ba322SStefano Zampini     {
15760c7d97c5SJed Brown       Vec         temp_vec;
1577b76ba322SStefano Zampini       PetscReal   value;
1578e6872a76SStefano Zampini       PetscInt    use_exact,use_exact_reduced;
15790c7d97c5SJed Brown 
1580a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
15810298fd71SBarry Smith       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
1582a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1583a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1584a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1585a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
158629622bf0SStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1587b76ba322SStefano Zampini       use_exact = 1;
15882fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1589ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1590e6872a76SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,(PetscBool)use_exact_reduced);CHKERRQ(ierr);
1591b76ba322SStefano Zampini       if (dbg_flag) {
1592a0ba757dSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1593a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1594a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1595a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1596674ae819SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
159729622bf0SStefano Zampini       }
1598674ae819SStefano Zampini       if (n_D && pcbddc->NullSpace && !use_exact_reduced && !pcbddc->inexact_prec_type) {
1599674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);
160029622bf0SStefano Zampini       }
1601d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
16020298fd71SBarry Smith       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
1603d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1604d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1605d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1606d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1607e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
160829622bf0SStefano Zampini       use_exact = 1;
16092fa5cd67SKarl Rupp       if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
1610ce94432eSBarry Smith       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
161129622bf0SStefano Zampini       if (dbg_flag) {
16120c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1613d49ef151SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
16140c7d97c5SJed Brown       }
1615e6872a76SStefano Zampini       if (n_R && pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
1616674ae819SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,is_R_local);
161729622bf0SStefano Zampini       }
1618b76ba322SStefano Zampini     }
16190c7d97c5SJed Brown     /* free Neumann problem's matrix */
16200c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
16210c7d97c5SJed Brown   }
16220c7d97c5SJed Brown 
16230c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
16240c7d97c5SJed Brown   {
16250c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
16260bdf917eSStefano Zampini     Mat          M1;
16270c7d97c5SJed Brown     Mat          C_CR;
16283b03a366Sstefano_zampini     Mat          AUXMAT;
16290c7d97c5SJed Brown     Vec          vec1_C;
16300c7d97c5SJed Brown     Vec          vec2_C;
16310c7d97c5SJed Brown     Vec          vec1_V;
16320c7d97c5SJed Brown     Vec          vec2_V;
1633e6872a76SStefano Zampini     IS           is_C_local,is_V_local,is_aux1;
1634e6872a76SStefano Zampini     ISLocalToGlobalMapping BtoNmap;
16350c7d97c5SJed Brown     PetscInt     *nnz;
1636e6872a76SStefano Zampini     PetscInt     *idx_V_B;
16370c7d97c5SJed Brown     PetscInt     *auxindices;
163853cdbc3dSStefano Zampini     PetscInt     index;
16390c7d97c5SJed Brown     PetscScalar* array2;
16400c7d97c5SJed Brown     MatFactorInfo matinfo;
164115aaf578SStefano Zampini     PetscBool    setsym=PETSC_FALSE,issym=PETSC_FALSE;
16420c7d97c5SJed Brown 
16430c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
16440c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
16450c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
16462fa5cd67SKarl Rupp     for (i=0;i<pcis->n;i++) auxindices[i]=i;
16470c7d97c5SJed Brown 
1648e6872a76SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1649e6872a76SStefano Zampini     /* vertices in boundary numbering */
1650e6872a76SStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1651e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
1652e6872a76SStefano Zampini     ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
1653e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
1654e6872a76SStefano Zampini     if (i != n_vertices) {
1655e6872a76SStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1656e6872a76SStefano Zampini     }
1657e6872a76SStefano Zampini 
16580c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
16593b03a366Sstefano_zampini     if (n_vertices) {
16600c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
16613b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
16620c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
16630c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
16640c7d97c5SJed Brown     }
1665534831adSStefano Zampini     if (n_constraints) {
16660c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
1667534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
16680c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
16690c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
16700c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
16710c7d97c5SJed Brown     }
16720c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
16733b03a366Sstefano_zampini     if (n_constraints) {
16740c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
16753b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
16760c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
16770298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,NULL);CHKERRQ(ierr);
16780c7d97c5SJed Brown 
167957a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
1680e6872a76SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
168157a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
168257a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
168357a90decSStefano Zampini 
16840c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
16853b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
16863b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
16873b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
168857a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
168957a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
16902fa5cd67SKarl Rupp         for (j=0;j<size_of_constraint;j++) array[row_cmat_indices[j]] = -row_cmat_values[j];
169157a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
169257a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
16932fa5cd67SKarl Rupp 
16943b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
169553cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
16962fa5cd67SKarl Rupp 
16973b03a366Sstefano_zampini         /* Set values */
16980c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
16993b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17000c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
17010c7d97c5SJed Brown       }
17020c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17030c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17040c7d97c5SJed Brown 
17050c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
17060c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1707d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
17083b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
17090c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
17100c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
17110c7d97c5SJed Brown 
17123b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1713d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
17143b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
17150c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
17160298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(M1,NULL);CHKERRQ(ierr);
17173b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
17180c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
17190c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
17200c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
17210c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
17220c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
17230c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
17240c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
17253b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17260c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
17270c7d97c5SJed Brown       }
17280c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17290c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17300c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
17310c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
17320c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
17330c7d97c5SJed Brown 
17340c7d97c5SJed Brown     }
17350c7d97c5SJed Brown 
17360c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
17373b03a366Sstefano_zampini     if (n_vertices) {
173815aaf578SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr);
1739534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1740534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1741534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
174215aaf578SStefano Zampini       ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17430c7d97c5SJed Brown     }
17440c7d97c5SJed Brown 
17450c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1746d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
17470c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
17480c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
17490298fd71SBarry Smith     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,NULL);CHKERRQ(ierr);
175029622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
1751d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
17520c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
17530c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
17540298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,NULL);CHKERRQ(ierr);
17550c7d97c5SJed Brown     }
17560c7d97c5SJed Brown 
1757e269702eSStefano Zampini     if (dbg_flag) {
17585b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*coarsefunctions_errors),&coarsefunctions_errors);CHKERRQ(ierr);
17595b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*constraints_errors),&constraints_errors);CHKERRQ(ierr);
17600c7d97c5SJed Brown     }
17613b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
17620c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
17630c7d97c5SJed Brown 
17640c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
17653b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++){
17660c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
17670c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
17680c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
17690c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
17700c7d97c5SJed Brown       /* solution of saddle point problem */
17710bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
17720bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17730c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
17743b03a366Sstefano_zampini       if (n_constraints) {
17750c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
17760c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
17770c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
17780c7d97c5SJed Brown       }
17790c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
17800c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
17810c7d97c5SJed Brown 
17820c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
17830c7d97c5SJed Brown       /* coarse basis functions */
17840c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
17850c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17860c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17870c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17883b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17890c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
17900c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
179129622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag  ) {
17920c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17930c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17940c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17953b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
17960c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
17970c7d97c5SJed Brown       }
17980c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
17990c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18002fa5cd67SKarl Rupp       for (j=0; j<n_vertices; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j];   /* WARNING -> column major ordering */
18010c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18023b03a366Sstefano_zampini       if (n_constraints) {
18030c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18042fa5cd67SKarl 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 */
18050c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18060c7d97c5SJed Brown       }
18070c7d97c5SJed Brown 
1808e269702eSStefano Zampini       if ( dbg_flag ) {
18090c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1810d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18110c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18120c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18132fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
18143b03a366Sstefano_zampini         array[ vertices[i] ] = one;
18150c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18160c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18170c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1818d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
18190c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18200c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18212fa5cd67SKarl Rupp         for (j=0;j<n_vertices;j++) array2[j]=array[j];
18220c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18233b03a366Sstefano_zampini         if (n_constraints) {
18240c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18252fa5cd67SKarl Rupp           for (j=0;j<n_constraints;j++) array2[j+n_vertices]=array[j];
18260c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18270c7d97c5SJed Brown         }
18280c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18290c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
18300c7d97c5SJed Brown         /* check saddle point solution */
1831534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
18323b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
18333b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
18343b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
18350c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18363b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
18370c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
18383b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
18390c7d97c5SJed Brown       }
18400c7d97c5SJed Brown     }
18410c7d97c5SJed Brown 
18423b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++){
1843d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
18440c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
18450c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
18460c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
18470c7d97c5SJed Brown       /* solution of saddle point problem */
18480c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
18490c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
18500c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
18513b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
18520c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
18530c7d97c5SJed Brown       /* coarse basis functions */
18543b03a366Sstefano_zampini       index=i+n_vertices;
18550c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
18560c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18570c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18580c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
185953cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18600c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
186129622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
18620c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18630c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18640c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
186553cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
18660c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
18670c7d97c5SJed Brown       }
18680c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
18693b03a366Sstefano_zampini       if (n_vertices) {
18700c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18712fa5cd67SKarl Rupp         for (j=0; j<n_vertices; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j]; /* WARNING -> column major ordering */
18720c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18730c7d97c5SJed Brown       }
18740c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18752fa5cd67SKarl 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 */
18760c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18770c7d97c5SJed Brown 
1878e269702eSStefano Zampini       if ( dbg_flag ) {
18790c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
188053cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18810c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18820c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18832fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
18840c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
18850c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18860c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
188753cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
18880c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18893b03a366Sstefano_zampini         if ( n_vertices) {
18900c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
18912fa5cd67SKarl Rupp           for (j=0;j<n_vertices;j++) array2[j]=-array[j];
18920c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
18930c7d97c5SJed Brown         }
18940c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
18953b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
18960c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
18970c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
18983972b0daSStefano Zampini         /* check saddle point solution */
1899534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
19003b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
190153cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
19023b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
19030c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
190453cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
19050c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
190653cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
19070c7d97c5SJed Brown       }
19080c7d97c5SJed Brown     }
19090c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19100c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
191129622bf0SStefano Zampini     if ( pcbddc->inexact_prec_type || dbg_flag ) {
19120c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19130c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19140c7d97c5SJed Brown     }
191515aaf578SStefano Zampini     /* compute other basis functions for non-symmetric problems */
191615aaf578SStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
191715aaf578SStefano Zampini     if ( !setsym || (setsym && !issym) ) {
191815aaf578SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
191915aaf578SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
192015aaf578SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
192115aaf578SStefano Zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_B,NULL);CHKERRQ(ierr);
192215aaf578SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag ) {
192315aaf578SStefano Zampini         ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
192415aaf578SStefano Zampini         ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
192515aaf578SStefano Zampini         ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
192615aaf578SStefano Zampini         ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_D,NULL);CHKERRQ(ierr);
192715aaf578SStefano Zampini       }
192815aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
192915aaf578SStefano Zampini         if (n_constraints) {
193015aaf578SStefano Zampini           ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
193115aaf578SStefano Zampini           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
193215aaf578SStefano Zampini           for (j=0;j<n_constraints;j++) {
193315aaf578SStefano Zampini             array[j]=coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i];
193415aaf578SStefano Zampini           }
193515aaf578SStefano Zampini           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
193615aaf578SStefano Zampini         }
193715aaf578SStefano Zampini         if (i<n_vertices) {
193815aaf578SStefano Zampini           ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
193915aaf578SStefano Zampini           ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
194015aaf578SStefano Zampini           ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
194115aaf578SStefano Zampini           ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
194215aaf578SStefano Zampini           ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
194315aaf578SStefano Zampini           if (n_constraints) {
194415aaf578SStefano Zampini             ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
194515aaf578SStefano Zampini           }
194615aaf578SStefano Zampini         } else {
194715aaf578SStefano Zampini           ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
194815aaf578SStefano Zampini         }
194915aaf578SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
195015aaf578SStefano Zampini         ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
195115aaf578SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195215aaf578SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195315aaf578SStefano Zampini         ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
195415aaf578SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
195515aaf578SStefano Zampini         ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
195615aaf578SStefano Zampini         if (i<n_vertices) {
195715aaf578SStefano Zampini           ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
195815aaf578SStefano Zampini         }
195915aaf578SStefano Zampini         if ( pcbddc->inexact_prec_type || dbg_flag  ) {
196015aaf578SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196115aaf578SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196215aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
196315aaf578SStefano Zampini           ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
196415aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
196515aaf578SStefano Zampini         }
196615aaf578SStefano Zampini 
196715aaf578SStefano Zampini         if ( dbg_flag ) {
196815aaf578SStefano Zampini           /* assemble subdomain vector on nodes */
196915aaf578SStefano Zampini           ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
197015aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
197115aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
197215aaf578SStefano Zampini           for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
197315aaf578SStefano Zampini           if (i<n_vertices) array[vertices[i]] = one;
197415aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
197515aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
197615aaf578SStefano Zampini           /* assemble subdomain vector of lagrange multipliers */
197715aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
197815aaf578SStefano Zampini           for (j=0;j<pcbddc->local_primal_size;j++) {
197915aaf578SStefano Zampini             array[j]=-coarse_submat_vals[j*pcbddc->local_primal_size+i];
198015aaf578SStefano Zampini           }
198115aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
198215aaf578SStefano Zampini           /* check saddle point solution */
198315aaf578SStefano Zampini           ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198415aaf578SStefano Zampini           ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
198515aaf578SStefano Zampini           ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
198615aaf578SStefano Zampini           ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
198715aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
198815aaf578SStefano Zampini           array[i]=array[i]+m_one; /* shift by the identity matrix */
198915aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
199015aaf578SStefano Zampini           ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
199115aaf578SStefano Zampini         }
199215aaf578SStefano Zampini       }
199315aaf578SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
199415aaf578SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
199515aaf578SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
199615aaf578SStefano Zampini         ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
199715aaf578SStefano Zampini         ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
199815aaf578SStefano Zampini       }
199915aaf578SStefano Zampini     }
200015aaf578SStefano Zampini     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
20010c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
200215aaf578SStefano Zampini     /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
200315aaf578SStefano Zampini     /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
20049d2fce94SStefano Zampini     if (dbg_flag) {
20050c7d97c5SJed Brown       Mat         coarse_sub_mat;
20060c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
200715aaf578SStefano Zampini       Mat         coarse_phi_D,coarse_phi_B;
200815aaf578SStefano Zampini       Mat         coarse_psi_D,coarse_psi_B;
200915aaf578SStefano Zampini       Mat         A_II,A_BB,A_IB,A_BI;
201019fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
20115b08dc53SStefano Zampini       PetscReal   real_value;
20120c7d97c5SJed Brown 
2013c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2014c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2015c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2016c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2017c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
2018c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
201915aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
202015aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
202115aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
202215aaf578SStefano Zampini       }
2023c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
20240c7d97c5SJed Brown 
20250c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
20260c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
20270c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
202815aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
202915aaf578SStefano Zampini         ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
203015aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
203115aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
203215aaf578SStefano Zampini         ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
203315aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
203415aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
203515aaf578SStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
203615aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
203715aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
203815aaf578SStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
203915aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
204015aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
204115aaf578SStefano Zampini       } else {
204253cdbc3dSStefano Zampini         ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
204353cdbc3dSStefano Zampini         ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
204453cdbc3dSStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
2045c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
204653cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
204753cdbc3dSStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
2048c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
204953cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
205015aaf578SStefano Zampini       }
205153cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
205253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
205353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
205415aaf578SStefano Zampini       ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
205515aaf578SStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
20565b08dc53SStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
20570c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
20580c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
20595b08dc53SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
206015aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
206115aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
206215aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
206315aaf578SStefano Zampini       }
206415aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
206515aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
206615aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
206715aaf578SStefano Zampini       }
206815aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
206915aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
207015aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
207115aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
207215aaf578SStefano Zampini         }
207315aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
207415aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
207515aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
207615aaf578SStefano Zampini         }
207715aaf578SStefano Zampini       }
20780c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
207953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
208053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
208153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
208253cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
208353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
208453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
208553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
208653cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
208753cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
208853cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
208915aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
209015aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
209115aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
209215aaf578SStefano Zampini       }
209315aaf578SStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
20940c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
20950c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
20960c7d97c5SJed Brown     }
20970c7d97c5SJed Brown     /* free memory */
20983b03a366Sstefano_zampini     if (n_vertices) {
209915aaf578SStefano Zampini       ierr = PetscFree(vertices);CHKERRQ(ierr);
21000c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
21010c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
21020c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
21030c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
21040c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
21050c7d97c5SJed Brown     }
2106534831adSStefano Zampini     if (n_constraints) {
21070c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
21080c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
21090c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
21100c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
21110c7d97c5SJed Brown     }
2112a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
2113a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2114a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
2115674ae819SStefano Zampini     ierr = PCBDDCSetUpCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
2116a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
21170c7d97c5SJed Brown   }
21180c7d97c5SJed Brown   /* free memory */
21190c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
2120674ae819SStefano Zampini 
21210c7d97c5SJed Brown   PetscFunctionReturn(0);
21220c7d97c5SJed Brown }
21230c7d97c5SJed Brown 
21240c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
21250c7d97c5SJed Brown 
21267cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
21277cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
21287cbb387bSStefano Zampini #include "metis.h"
21297cbb387bSStefano Zampini #define MetisInt    idx_t
21307cbb387bSStefano Zampini #define MetisScalar real_t
21317cbb387bSStefano Zampini #endif
21327cbb387bSStefano Zampini 
21330c7d97c5SJed Brown #undef __FUNCT__
2134674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
2135674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
21360c7d97c5SJed Brown {
2137674ae819SStefano Zampini 
2138674ae819SStefano Zampini 
21390c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
21400c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
21410c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
2142ce94432eSBarry Smith   MPI_Comm  prec_comm;
21430c7d97c5SJed Brown   MPI_Comm  coarse_comm;
21440c7d97c5SJed Brown 
2145674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
2146674ae819SStefano Zampini 
21470c7d97c5SJed Brown   /* common to all choiches */
21480c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
21490c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
21500c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
21510c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
21520c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
21530c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
21540c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
21550c7d97c5SJed Brown   PetscMPIInt master_proc=0;
21560c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
21570c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
21585b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
21590c7d97c5SJed Brown   PetscMPIInt count_recv=0;
21605b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
21610c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
21620c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
21630c7d97c5SJed Brown   /* some other variables */
21640c7d97c5SJed Brown   PetscErrorCode ierr;
216519fd82e9SBarry Smith   MatType coarse_mat_type;
216619fd82e9SBarry Smith   PCType  coarse_pc_type;
216719fd82e9SBarry Smith   KSPType coarse_ksp_type;
216853cdbc3dSStefano Zampini   PC pc_temp;
21694fad6a16SStefano Zampini   PetscInt i,j,k;
21703b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
2171e269702eSStefano Zampini   /* verbose output viewer */
2172e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
21735b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
2174142dfd88SStefano Zampini 
2175ea7e1babSStefano Zampini   PetscInt      offset,offset2;
2176a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
2177523858cfSStefano Zampini   PetscInt      *dnz,*onz;
2178142dfd88SStefano Zampini 
2179142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
21800c7d97c5SJed Brown 
21810c7d97c5SJed Brown   PetscFunctionBegin;
21824b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
21830c7d97c5SJed Brown   ins_local_primal_indices = 0;
21840c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
21850c7d97c5SJed Brown   localsizes2              = 0;
21860c7d97c5SJed Brown   localdispl2              = 0;
21870c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
21880c7d97c5SJed Brown   coarse_ISLG              = 0;
21890c7d97c5SJed Brown 
219053cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
219153cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
2192142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
2193142dfd88SStefano Zampini 
2194beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
2195beed3852SStefano Zampini   {
2196674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
2197ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
2198ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
2199ef028eecSStefano Zampini 
2200ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
2201beed3852SStefano Zampini 
2202beed3852SStefano Zampini     /* Construct needed data structures for message passing */
2203ffe5efe1SStefano Zampini     j = 0;
2204142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2205ffe5efe1SStefano Zampini       j = size_prec_comm;
2206ffe5efe1SStefano Zampini     }
2207ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
2208ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2209beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
2210142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22115619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
2212ffe5efe1SStefano Zampini     } else {
2213ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
2214ffe5efe1SStefano Zampini     }
2215beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
2216ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
2217beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
2218beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
2219beed3852SStefano Zampini     }
2220beed3852SStefano Zampini 
2221da1bb401SStefano Zampini     /* First let's count coarse dofs.
2222beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
2223beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
2224beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2225ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
2226674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
2227674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
2228674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2229674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
2230674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
2231674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2232ef028eecSStefano Zampini     /* Compute number of coarse dofs */
2233674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
2234ef028eecSStefano Zampini 
2235ef028eecSStefano Zampini     if (dbg_flag) {
22362e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22372e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
22382e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
22392e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
22402e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22412fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
2242beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22432e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2244da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2245da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2246da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2247da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2248da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22492e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
22502e8d2280SStefano Zampini         if (array[i] == 1.0) {
22512e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
22522e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
22532e8d2280SStefano Zampini         }
22542e8d2280SStefano Zampini       }
22552e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22562e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
22575b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
22582e8d2280SStefano Zampini       }
2259da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
22602e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2261da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2262da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2263da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
22642e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
22652e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22662e8d2280SStefano Zampini     }
2267142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
22680bdf917eSStefano Zampini   }
22690bdf917eSStefano Zampini 
22702e8d2280SStefano Zampini   if (dbg_flag) {
22717cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
22729d9e44b6SStefano Zampini     if (dbg_flag > 1) {
2273674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
22742e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2275674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2276674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
2277674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
2278674ae819SStefano Zampini       }
22792e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22802e8d2280SStefano Zampini     }
22812e8d2280SStefano Zampini   }
22822e8d2280SStefano Zampini 
2283a929c220SStefano Zampini   im_active = 0;
22842fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
2285a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
22860bdf917eSStefano Zampini 
22870bdf917eSStefano Zampini   /* adapt coarse problem type */
22887cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
22894fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22904fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2291a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
22920bdf917eSStefano Zampini         if (dbg_flag) {
2293a929c220SStefano 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);
22940bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
22950bdf917eSStefano Zampini         }
22960bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2297142dfd88SStefano Zampini       }
22984fad6a16SStefano Zampini     } else {
22994fad6a16SStefano Zampini       if (dbg_flag) {
2300a929c220SStefano 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);
23014fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
23024fad6a16SStefano Zampini       }
23034fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
23044fad6a16SStefano Zampini     }
23054fad6a16SStefano Zampini   }
23067cbb387bSStefano Zampini #else
23077cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
23087cbb387bSStefano Zampini #endif
2309beed3852SStefano Zampini 
23100c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
23110c7d97c5SJed Brown 
2312da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
23130c7d97c5SJed Brown     {
23147cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
23150c7d97c5SJed Brown       /* we need additional variables */
23160c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
23170c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
23180c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
23190c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
23200c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
23210c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
23220c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
23230c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
23240c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
23250c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
23260c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
23270c7d97c5SJed Brown       MetisInt    *faces_adjncy;
23280c7d97c5SJed Brown       MetisInt    *faces_xadj;
23290c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
23300c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
23310c7d97c5SJed Brown       PetscInt    *array_int;
23320c7d97c5SJed Brown       PetscMPIInt my_faces=0;
23330c7d97c5SJed Brown       PetscMPIInt total_faces=0;
23343828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
23350c7d97c5SJed Brown 
23360c7d97c5SJed Brown       /* define some quantities */
23370c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
23380c7d97c5SJed Brown       coarse_mat_type = MATIS;
23390c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
2340142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
23410c7d97c5SJed Brown 
23420c7d97c5SJed Brown       /* details of coarse decomposition */
2343a929c220SStefano Zampini       n_subdomains = active_procs;
23440c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2345a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
23463828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
23473828260eSStefano Zampini 
2348a929c220SStefano Zampini #if 0
2349a929c220SStefano Zampini       PetscMPIInt *old_ranks;
2350a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2351a929c220SStefano Zampini       MatPartitioning mat_part;
2352a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2353a929c220SStefano Zampini       PetscViewer viewer_test;
2354a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
2355a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
2356a929c220SStefano Zampini       Mat         mat_adj;
2357a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2358a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2359a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2360a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2361a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2362a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2363a929c220SStefano Zampini       if (im_active) {
2364a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2365a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2366a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2367a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2368a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2369674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2370674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2371a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2372a929c220SStefano Zampini         k = pcis->n_neigh-1;
2373a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2374a929c220SStefano Zampini         ii[0]=0;
2375a929c220SStefano Zampini         ii[1]=k;
2376a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2377674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2378a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
23790298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2380a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2381a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2382a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2383a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2384a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2385a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2386a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2387a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2388a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2389a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2390a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2391a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2392a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2393a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2394a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2395a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2396a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2397a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2398a929c220SStefano Zampini       }
2399a929c220SStefano Zampini #endif
2400a929c220SStefano Zampini 
24014fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
24020c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
24033828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
24040c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
24050c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
24060c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
24070c7d97c5SJed Brown         }
24080c7d97c5SJed Brown       }
24090c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
24100c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
24117cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
24120c7d97c5SJed Brown             my_faces++;
24130c7d97c5SJed Brown             break;
24140c7d97c5SJed Brown           }
24150c7d97c5SJed Brown         }
24160c7d97c5SJed Brown       }
24170c7d97c5SJed Brown 
241853cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
24190c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
24200c7d97c5SJed Brown       my_faces=0;
24210c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
24220c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
24237cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
24240c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
24250c7d97c5SJed Brown             my_faces++;
24260c7d97c5SJed Brown             break;
24270c7d97c5SJed Brown           }
24280c7d97c5SJed Brown         }
24290c7d97c5SJed Brown       }
24300c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24310c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
24320c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
24330c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
24340c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
24350c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
24360c7d97c5SJed Brown       }
243753cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
24380c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24390c7d97c5SJed Brown         faces_xadj[0]=0;
24400c7d97c5SJed Brown         faces_displacements[0]=0;
24410c7d97c5SJed Brown         j=0;
24420c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
24430c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
24440c7d97c5SJed Brown           if (number_of_faces[i-1]) {
24450c7d97c5SJed Brown             j++;
24460c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
24470c7d97c5SJed Brown           }
24480c7d97c5SJed Brown         }
24490c7d97c5SJed Brown       }
245053cdbc3dSStefano 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);
24510c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
24520c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
24530c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
24543828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
24550c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
24560c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
24570c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
24580c7d97c5SJed Brown       }
24590c7d97c5SJed Brown 
24600c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
2461674ae819SStefano Zampini 
24623828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
2463674ae819SStefano Zampini 
24640c7d97c5SJed Brown         ncon=1;
24650c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
24660c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
24670c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
24680c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
24690c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
24700c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
24710c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
24724fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
24733828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
24743828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
24753828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
24760c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2477674ae819SStefano 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);
24783828260eSStefano Zampini           } else {
24793828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2480674ae819SStefano 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);
24813828260eSStefano Zampini           }
24824fad6a16SStefano Zampini         } else {
24832fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
24844fad6a16SStefano Zampini         }
24850c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
24860c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
24870bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
24882fa5cd67SKarl Rupp 
24890c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
24902fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
24912fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
24920c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
24930c7d97c5SJed Brown       }
24940c7d97c5SJed Brown 
24950c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
24960c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2497da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2498da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
24990c7d97c5SJed Brown       }
2500da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2501da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
250253cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
25030c7d97c5SJed Brown 
25040c7d97c5SJed Brown       if ( coarse_color == 0 ) {
250553cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
250653cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
25070c7d97c5SJed Brown       } else {
25080c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
25090c7d97c5SJed Brown       }
25100c7d97c5SJed Brown 
25117cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
25120c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
25130c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
25140bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
25150bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
25160c7d97c5SJed Brown         /* some initializations */
25170c7d97c5SJed Brown         displacements_recv[0]=0;
25180bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
25190c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
25200bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
25210bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
25222fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
25230bdf917eSStefano Zampini           }
25240bdf917eSStefano Zampini         }
25250c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
25262fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
25272fa5cd67SKarl Rupp 
25280c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
25290c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
25300c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
25313828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
25320c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
25330c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
25343828260eSStefano Zampini               total_count_recv[j]+=1;
25350c7d97c5SJed Brown             }
25360c7d97c5SJed Brown           }
25370c7d97c5SJed Brown         }
2538da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
25393828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
25403828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
25413828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
25423828260eSStefano Zampini           }
25433828260eSStefano Zampini           printf("\n");
2544da1bb401SStefano Zampini         }*/
25450c7d97c5SJed Brown 
25460c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
25470bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
25480bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
25490bdf917eSStefano Zampini         }
2550da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2551674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
25523828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
25533828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
25543828260eSStefano Zampini           } else {
25553828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
25563828260eSStefano Zampini           }
2557da1bb401SStefano Zampini         printf("\n");*/
25580c7d97c5SJed Brown       }
25590c7d97c5SJed Brown 
25600c7d97c5SJed Brown       /* Scatter new decomposition for send details */
256153cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
25620c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
25630c7d97c5SJed Brown       if ( coarse_color == 0) {
256453cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
25650c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
256653cdbc3dSStefano 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);
25670c7d97c5SJed Brown       }
25680c7d97c5SJed Brown 
2569da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2570da1bb401SStefano Zampini       if (coarse_color == 0) {
2571da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2572da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
2573da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2574da1bb401SStefano Zampini         printf("\n");
2575da1bb401SStefano Zampini       }*/
25760c7d97c5SJed Brown 
25770c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
25780bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2579da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
25800bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
25810c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
25820c7d97c5SJed Brown       }
25837cbb387bSStefano Zampini #endif
25840c7d97c5SJed Brown       break;
25850c7d97c5SJed Brown     }
25860c7d97c5SJed Brown 
25870c7d97c5SJed Brown     case(REPLICATED_BDDC):
25880c7d97c5SJed Brown 
25890c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
25900c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
25910c7d97c5SJed Brown       coarse_pc_type  = PCLU;
259253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
25930c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
25940c7d97c5SJed Brown       active_rank = rank_prec_comm;
25950c7d97c5SJed Brown       break;
25960c7d97c5SJed Brown 
25970c7d97c5SJed Brown     case(PARALLEL_BDDC):
25980c7d97c5SJed Brown 
25990c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2600674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
26010c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
260253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
26030c7d97c5SJed Brown       coarse_comm = prec_comm;
26040c7d97c5SJed Brown       active_rank = rank_prec_comm;
26050c7d97c5SJed Brown       break;
26060c7d97c5SJed Brown 
26070c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
26080c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
2609674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
26100c7d97c5SJed Brown       coarse_pc_type = PCLU;
261153cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
26120c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
26130c7d97c5SJed Brown       active_rank = master_proc;
26140c7d97c5SJed Brown       break;
26150c7d97c5SJed Brown   }
26160c7d97c5SJed Brown 
26170c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
26180c7d97c5SJed Brown 
26190c7d97c5SJed Brown     case(SCATTERS_BDDC):
26200c7d97c5SJed Brown       {
26210c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
26220c7d97c5SJed Brown 
26232e8d2280SStefano Zampini           IS coarse_IS;
26242e8d2280SStefano Zampini 
2625523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2626523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2627523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
2628523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2629523858cfSStefano Zampini             /* nonzeros */
2630523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2631523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2632523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2633523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
2634523858cfSStefano Zampini             }
2635523858cfSStefano Zampini           } else {
26360c7d97c5SJed Brown             PetscMPIInt send_size;
2637ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
26380c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
26390c7d97c5SJed Brown             PetscInt    ii,jj;
26400c7d97c5SJed Brown             MPI_Request *requests;
2641ef028eecSStefano Zampini 
2642523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2643523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
2644523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
2645523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2646523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
2647523858cfSStefano Zampini             j = 0;
2648523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2649523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
2650523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
2651523858cfSStefano Zampini             }
2652523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
2653523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
26540c7d97c5SJed Brown             /* allocate auxiliary space */
2655523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
26560c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
26570c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
26580c7d97c5SJed Brown             /* allocate stuffs for message massing */
26590c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2660523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2661523858cfSStefano Zampini             /* send indices to be inserted */
2662523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2663523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
2664523858cfSStefano 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);
2665523858cfSStefano Zampini             }
2666523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2667523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
2668ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2669ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
2670ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
2671ef028eecSStefano Zampini               }
2672ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2673523858cfSStefano Zampini             }
2674523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2675ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2676ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2677ef028eecSStefano Zampini             }
26780c7d97c5SJed Brown             j = 0;
26790c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
26802e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
26812e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
26820c7d97c5SJed Brown               localdispl2[i] = j;
26830c7d97c5SJed Brown               j += localsizes2[i];
2684523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
26854fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
26862e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
26874fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
26880c7d97c5SJed Brown               }
26894fad6a16SStefano Zampini             }
2690523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
26910c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
26920c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
26930c7d97c5SJed Brown             ins_local_primal_size = 0;
2694ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
2695ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
26960c7d97c5SJed Brown                 ins_local_primal_size++;
2697ea7e1babSStefano Zampini               }
2698ea7e1babSStefano Zampini             }
26990c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
27000c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
27010c7d97c5SJed Brown             j = 0;
2702ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
2703ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
27042e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
27052e8d2280SStefano Zampini                 j++;
2706ea7e1babSStefano Zampini               }
2707ea7e1babSStefano Zampini             }
2708523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2709523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2710523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2711523858cfSStefano Zampini             }
2712523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2713523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2714523858cfSStefano 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);
2715523858cfSStefano Zampini             }
2716523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2717523858cfSStefano Zampini             /* nonzeros */
2718523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2719523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
27200c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
27210c7d97c5SJed Brown             j=0;
27220c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
27230c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
27240c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
27250c7d97c5SJed Brown               } else {
27260c7d97c5SJed Brown                 aux_ins_indices[i]=j;
27270c7d97c5SJed Brown                 j++;
27280c7d97c5SJed Brown               }
27290c7d97c5SJed Brown             }
27304fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
2731523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
2732523858cfSStefano Zampini               for (k=0;k<j;k++) {
2733523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
27340c7d97c5SJed Brown               }
27350c7d97c5SJed Brown             }
2736523858cfSStefano Zampini             /* check */
2737523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2738523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2739523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
27400c7d97c5SJed Brown               }
27410c7d97c5SJed Brown             }
27420c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
27430c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
27440c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
27454fad6a16SStefano Zampini           }
27460c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
2747142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
27480c7d97c5SJed Brown           coarse_comm = prec_comm;
27490c7d97c5SJed Brown           active_rank = rank_prec_comm;
27500c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
27510c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
27520c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
27532e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
27540c7d97c5SJed Brown           /* arrays for values insertion */
27550c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
27562e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
27570c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
27580c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
27590c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
27604fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
27614fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
27624fad6a16SStefano Zampini             }
27630c7d97c5SJed Brown           }
27640c7d97c5SJed Brown         }
27650c7d97c5SJed Brown         break;
2766674ae819SStefano Zampini 
27670c7d97c5SJed Brown     }
27680c7d97c5SJed Brown 
27690c7d97c5SJed Brown     case(GATHERS_BDDC):
27700c7d97c5SJed Brown       {
2771674ae819SStefano Zampini 
27720c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
2773ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
27740c7d97c5SJed Brown 
27750c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
27760c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
27770bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
27780c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
27790c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
27800c7d97c5SJed Brown           /* arrays for values insertion */
27812fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
27820c7d97c5SJed Brown           localdispl2[0]=0;
27832fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
27840c7d97c5SJed Brown           j=0;
27852fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
27860c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
27870c7d97c5SJed Brown         }
27880c7d97c5SJed Brown 
27890c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
27900c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2791ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
27922fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
27932fa5cd67SKarl Rupp 
27940c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2795ef028eecSStefano 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);
279653cdbc3dSStefano 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);
27970c7d97c5SJed Brown         } else {
2798ef028eecSStefano 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);
279953cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
28000c7d97c5SJed Brown         }
2801ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
28020c7d97c5SJed Brown         break;
2803da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
28040c7d97c5SJed Brown   }
28050c7d97c5SJed Brown 
28060c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
28070c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2808142dfd88SStefano Zampini 
2809142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2810142dfd88SStefano Zampini 
28110c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
28120c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
28130c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
28140c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);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(pcbddc->coarse_mat);CHKERRQ(ierr);
2818da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
28193b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
28200c7d97c5SJed Brown     } else {
28214fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
28223b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
28230c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2824674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2825674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
28263b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2827da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2828a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
28290c7d97c5SJed Brown     }
2830142dfd88SStefano Zampini     /* preallocation */
2831142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2832ef028eecSStefano Zampini 
2833674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2834ef028eecSStefano Zampini 
2835142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2836142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2837674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2838ef028eecSStefano Zampini 
2839142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2840ef028eecSStefano Zampini 
2841ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2842ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2843ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2844ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2845ef028eecSStefano Zampini 
2846ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2847674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2848ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2849ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2850ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2851ef028eecSStefano Zampini 
2852ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2853ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2854ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2855ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2856ef028eecSStefano Zampini 
2857ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2858ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2859142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2860ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2861ef028eecSStefano Zampini             row_ownership[j]=i;
2862142dfd88SStefano Zampini           }
2863142dfd88SStefano Zampini         }
2864ef028eecSStefano Zampini 
2865ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2866ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2867ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2868ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2869ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2870ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2871ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2872ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2873142dfd88SStefano Zampini             } else {
2874ef028eecSStefano Zampini               my_onz[i] += 1.0;
2875142dfd88SStefano Zampini             }
2876ef028eecSStefano Zampini             if (i != j) {
2877ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2878ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2879ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2880142dfd88SStefano Zampini               } else {
2881ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2882142dfd88SStefano Zampini               }
2883142dfd88SStefano Zampini             }
2884142dfd88SStefano Zampini           }
2885142dfd88SStefano Zampini         }
2886ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2887ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2888a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2889ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2890ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2891a929c220SStefano Zampini         }
2892ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2893ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2894ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2895ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2896ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2897ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
28985b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
28992fa5cd67SKarl Rupp 
2900ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2901ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
29025b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
29032fa5cd67SKarl Rupp 
2904ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2905ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2906ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2907ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2908ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2909ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2910142dfd88SStefano Zampini       } else {
2911142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2912142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2913142dfd88SStefano Zampini           offset2=localdispl2[k];
2914142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2915ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2916ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2917ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2918ef028eecSStefano Zampini           }
2919142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2920142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2921142dfd88SStefano Zampini           }
2922ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2923142dfd88SStefano Zampini         }
2924142dfd88SStefano Zampini       }
29252fa5cd67SKarl Rupp 
2926142dfd88SStefano Zampini       /* check */
2927142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
29282fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
29292fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2930142dfd88SStefano Zampini       }
2931d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2932d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2933142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2934142dfd88SStefano Zampini     } else {
2935523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2936523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2937142dfd88SStefano Zampini     }
2938142dfd88SStefano Zampini     /* insert values */
2939523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
29400c7d97c5SJed 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);
2941523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2942523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2943523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2944523858cfSStefano 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);
2945523858cfSStefano Zampini       } else {
2946523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2947523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2948523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2949523858cfSStefano Zampini           offset2 = localdispl2[k];
2950523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2951ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2952ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2953ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2954ef028eecSStefano Zampini           }
2955523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2956523858cfSStefano 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);
2957ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2958523858cfSStefano Zampini         }
2959523858cfSStefano Zampini       }
2960523858cfSStefano Zampini       ins_local_primal_indices = 0;
2961523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2962ea7e1babSStefano Zampini     } else {
2963ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2964ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2965ea7e1babSStefano Zampini         offset2=localdispl2[k];
2966ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2967ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2968ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2969ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2970ef028eecSStefano Zampini         }
2971ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2972ea7e1babSStefano 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);
2973ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2974ea7e1babSStefano Zampini       }
2975ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2976ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2977ea7e1babSStefano Zampini     }
29780c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29790c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2980142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2981142dfd88SStefano Zampini     if (issym) {
2982142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2983142dfd88SStefano Zampini     }
29840c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
29850bdf917eSStefano Zampini   }
29860bdf917eSStefano Zampini 
29870bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
29880bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
29890bdf917eSStefano Zampini      IS local_IS,global_IS;
29900bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
29910bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
29920bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
29930bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
29940bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
29950bdf917eSStefano Zampini   }
29960bdf917eSStefano Zampini 
2997a929c220SStefano Zampini   /* free memory no longer needed */
2998a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2999a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
3000a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
3001a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
3002a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
3003a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
3004a929c220SStefano Zampini 
3005674ae819SStefano Zampini   /* Compute coarse null space */
3006674ae819SStefano Zampini   CoarseNullSpace = 0;
30070bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
3008674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
30090bdf917eSStefano Zampini   }
30100bdf917eSStefano Zampini 
30110bdf917eSStefano Zampini   /* KSP for coarse problem */
30120bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
30132e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
30140bdf917eSStefano Zampini 
301553cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
301653cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
301753cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
30183b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
301953cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
302053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
302153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
30220c7d97c5SJed Brown     /* Allow user's customization */
3023da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
30240c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
302553cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
30264fad6a16SStefano Zampini       i = pcbddc->current_level+1;
30274fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
30284fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
30294fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
303053cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
3031674ae819SStefano Zampini       if (CoarseNullSpace) {
3032674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
3033674ae819SStefano Zampini       }
30344fad6a16SStefano Zampini       if (dbg_flag) {
30354fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
30364fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
303753cdbc3dSStefano Zampini       }
3038674ae819SStefano Zampini     } else {
3039674ae819SStefano Zampini       if (CoarseNullSpace) {
3040674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
3041674ae819SStefano Zampini       }
30424fad6a16SStefano Zampini     }
30434fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
304453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
3045142dfd88SStefano Zampini 
30460298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
30472e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
30482e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
30492e8d2280SStefano Zampini     if (j == 1) {
30502e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
30512e8d2280SStefano Zampini       if (isbddc) {
30522e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
30535619798eSStefano Zampini       }
30545619798eSStefano Zampini     }
30550c7d97c5SJed Brown   }
3056a929c220SStefano Zampini   /* Check coarse problem if requested */
3057142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
3058142dfd88SStefano Zampini     KSP check_ksp;
3059142dfd88SStefano Zampini     PC  check_pc;
3060142dfd88SStefano Zampini     Vec check_vec;
3061142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
306219fd82e9SBarry Smith     KSPType check_ksp_type;
30630c7d97c5SJed Brown 
3064142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
3065142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
3066142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
30670bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
3068142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
30692fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
30702fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
3071142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
3072142dfd88SStefano Zampini     } else {
3073142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
3074142dfd88SStefano Zampini     }
3075142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
3076142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
3077142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
3078142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
3079142dfd88SStefano Zampini     /* create random vec */
3080142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
30810298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
3082674ae819SStefano Zampini     if (CoarseNullSpace) {
30831cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
3084674ae819SStefano Zampini     }
3085142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3086142dfd88SStefano Zampini     /* solve coarse problem */
3087142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3088674ae819SStefano Zampini     if (CoarseNullSpace) {
30891cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
3090674ae819SStefano Zampini     }
3091142dfd88SStefano Zampini     /* check coarse problem residual error */
3092142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
3093142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3094142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3095142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
3096142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
3097142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
3098142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3099142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
3100142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
3101142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
3102e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
31033b03a366Sstefano_zampini     }
3104142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
3105142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
3106142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
310753cdbc3dSStefano Zampini   }
3108674ae819SStefano Zampini   if (dbg_flag) {
3109da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3110da1bb401SStefano Zampini   }
3111674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
3112a0ba757dSStefano Zampini 
31130c7d97c5SJed Brown   PetscFunctionReturn(0);
31140c7d97c5SJed Brown }
31150c7d97c5SJed Brown 
3116