xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision aa0d41d463ae17ff6de1da0e4fb594266144f895)
153cdbc3dSStefano Zampini /* TODOLIST
2da1bb401SStefano Zampini    DofSplitting and DM attached to pc?
3da1bb401SStefano Zampini    Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
4a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
5a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
6a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
7674ae819SStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in PCBDDCAnalyzeInterface?
8a0ba757dSStefano Zampini    code refactoring:
9a0ba757dSStefano Zampini      - pick up better names for static functions
10a0ba757dSStefano Zampini    change options structure:
11a0ba757dSStefano Zampini      - insert BDDC into MG framework?
12a0ba757dSStefano Zampini    provide other ops? Ask to developers
13a0ba757dSStefano Zampini    remove all unused printf
14a0ba757dSStefano Zampini    man pages
1553cdbc3dSStefano Zampini */
160c7d97c5SJed Brown 
1753cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
180c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
190c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2053cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2153cdbc3dSStefano Zampini 
22674ae819SStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23674ae819SStefano Zampini #include "bddcprivate.h"
243b03a366Sstefano_zampini #include <petscblaslapack.h>
25674ae819SStefano Zampini 
26674ae819SStefano Zampini /* prototypes for static functions contained in bddc.c */
27674ae819SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC,PetscInt);
28674ae819SStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC);
29674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC,PetscScalar*);
30674ae819SStefano Zampini 
310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
320c7d97c5SJed Brown #undef __FUNCT__
330c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
340c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
350c7d97c5SJed Brown {
360c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
370c7d97c5SJed Brown   PetscErrorCode ierr;
380c7d97c5SJed Brown 
390c7d97c5SJed Brown   PetscFunctionBegin;
400c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Verbose debugging of main data structures */
429d9e44b6SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,NULL);CHKERRQ(ierr);
430c7d97c5SJed Brown   /* Some customization for default primal space */
440298fd71SBarry 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);
450298fd71SBarry 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);
460298fd71SBarry 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);
470298fd71SBarry 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);
480c7d97c5SJed Brown   /* Coarse solver context */
496c667b0aSStefano 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 */
500298fd71SBarry 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);
510c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
520298fd71SBarry 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);
53674ae819SStefano 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);
54674ae819SStefano 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);
55674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
56674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
57674ae819SStefano Zampini   }
580298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
590298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
60674ae819SStefano 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);
610c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
620c7d97c5SJed Brown   PetscFunctionReturn(0);
630c7d97c5SJed Brown }
640c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
65674ae819SStefano Zampini #undef __FUNCT__
66674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
67674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
68674ae819SStefano Zampini {
69674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
70674ae819SStefano Zampini   PetscErrorCode ierr;
711e6b0712SBarry Smith 
72674ae819SStefano Zampini   PetscFunctionBegin;
73674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
74674ae819SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
75674ae819SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
76674ae819SStefano Zampini   PetscFunctionReturn(0);
77674ae819SStefano Zampini }
78674ae819SStefano Zampini #undef __FUNCT__
79674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
80674ae819SStefano Zampini /*@
81674ae819SStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC.
82674ae819SStefano Zampini 
83674ae819SStefano Zampini    Not collective
84674ae819SStefano Zampini 
85674ae819SStefano Zampini    Input Parameters:
86674ae819SStefano Zampini +  pc - the preconditioning context
87674ae819SStefano Zampini -  PrimalVertices - index sets of primal vertices in local numbering
88674ae819SStefano Zampini 
89674ae819SStefano Zampini    Level: intermediate
90674ae819SStefano Zampini 
91674ae819SStefano Zampini    Notes:
92674ae819SStefano Zampini 
93674ae819SStefano Zampini .seealso: PCBDDC
94674ae819SStefano Zampini @*/
95674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
96674ae819SStefano Zampini {
97674ae819SStefano Zampini   PetscErrorCode ierr;
98674ae819SStefano Zampini 
99674ae819SStefano Zampini   PetscFunctionBegin;
100674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
101674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
102674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
103674ae819SStefano Zampini   PetscFunctionReturn(0);
104674ae819SStefano Zampini }
105674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
1060c7d97c5SJed Brown #undef __FUNCT__
1070c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
10853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
1090c7d97c5SJed Brown {
1100c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1110c7d97c5SJed Brown 
1120c7d97c5SJed Brown   PetscFunctionBegin;
1130c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
1140c7d97c5SJed Brown   PetscFunctionReturn(0);
1150c7d97c5SJed Brown }
1161e6b0712SBarry Smith 
1170c7d97c5SJed Brown #undef __FUNCT__
1180c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
11953cdbc3dSStefano Zampini /*@
1209c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
12153cdbc3dSStefano Zampini 
1229c0446d6SStefano Zampini    Not collective
12353cdbc3dSStefano Zampini 
12453cdbc3dSStefano Zampini    Input Parameters:
12553cdbc3dSStefano Zampini +  pc - the preconditioning context
12653cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
12753cdbc3dSStefano Zampini 
12853cdbc3dSStefano Zampini    Level: intermediate
12953cdbc3dSStefano Zampini 
13053cdbc3dSStefano Zampini    Notes:
131da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
13253cdbc3dSStefano Zampini 
13353cdbc3dSStefano Zampini .seealso: PCBDDC
13453cdbc3dSStefano Zampini @*/
1350c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
1360c7d97c5SJed Brown {
1370c7d97c5SJed Brown   PetscErrorCode ierr;
1380c7d97c5SJed Brown 
1390c7d97c5SJed Brown   PetscFunctionBegin;
1400c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1410c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
1420c7d97c5SJed Brown   PetscFunctionReturn(0);
1430c7d97c5SJed Brown }
1440c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1450c7d97c5SJed Brown #undef __FUNCT__
1464fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
1474fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
1484fad6a16SStefano Zampini {
1494fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1504fad6a16SStefano Zampini 
1514fad6a16SStefano Zampini   PetscFunctionBegin;
1524fad6a16SStefano Zampini   pcbddc->coarsening_ratio=k;
1534fad6a16SStefano Zampini   PetscFunctionReturn(0);
1544fad6a16SStefano Zampini }
1551e6b0712SBarry Smith 
1564fad6a16SStefano Zampini #undef __FUNCT__
1574fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
1584fad6a16SStefano Zampini /*@
1594fad6a16SStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
1604fad6a16SStefano Zampini 
1614fad6a16SStefano Zampini    Logically collective on PC
1624fad6a16SStefano Zampini 
1634fad6a16SStefano Zampini    Input Parameters:
1644fad6a16SStefano Zampini +  pc - the preconditioning context
1654fad6a16SStefano Zampini -  k - coarsening ratio
1664fad6a16SStefano Zampini 
1674fad6a16SStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
1684fad6a16SStefano Zampini 
1694fad6a16SStefano Zampini    Level: intermediate
1704fad6a16SStefano Zampini 
1714fad6a16SStefano Zampini    Notes:
1724fad6a16SStefano Zampini 
1734fad6a16SStefano Zampini .seealso: PCBDDC
1744fad6a16SStefano Zampini @*/
1754fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
1764fad6a16SStefano Zampini {
1774fad6a16SStefano Zampini   PetscErrorCode ierr;
1784fad6a16SStefano Zampini 
1794fad6a16SStefano Zampini   PetscFunctionBegin;
1804fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1814fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
1824fad6a16SStefano Zampini   PetscFunctionReturn(0);
1834fad6a16SStefano Zampini }
1844fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1851e6b0712SBarry Smith 
1864fad6a16SStefano Zampini #undef __FUNCT__
1874fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
1884fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
1894fad6a16SStefano Zampini {
1904fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1914fad6a16SStefano Zampini 
1924fad6a16SStefano Zampini   PetscFunctionBegin;
1934fad6a16SStefano Zampini   pcbddc->max_levels=max_levels;
1944fad6a16SStefano Zampini   PetscFunctionReturn(0);
1954fad6a16SStefano Zampini }
1961e6b0712SBarry Smith 
1974fad6a16SStefano Zampini #undef __FUNCT__
1984fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels"
1994fad6a16SStefano Zampini /*@
2004fad6a16SStefano Zampini  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
2014fad6a16SStefano Zampini 
2024fad6a16SStefano Zampini    Logically collective on PC
2034fad6a16SStefano Zampini 
2044fad6a16SStefano Zampini    Input Parameters:
2054fad6a16SStefano Zampini +  pc - the preconditioning context
2064fad6a16SStefano Zampini -  max_levels - the maximum number of levels
2074fad6a16SStefano Zampini 
2084fad6a16SStefano Zampini    Default value is 1, i.e. coarse problem will be solved inexactly with one application
2094fad6a16SStefano Zampini    of PCBDDC preconditioner if the multilevel approach is requested.
2104fad6a16SStefano Zampini 
2114fad6a16SStefano Zampini    Level: intermediate
2124fad6a16SStefano Zampini 
2134fad6a16SStefano Zampini    Notes:
2144fad6a16SStefano Zampini 
2154fad6a16SStefano Zampini .seealso: PCBDDC
2164fad6a16SStefano Zampini @*/
2174fad6a16SStefano Zampini PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
2184fad6a16SStefano Zampini {
2194fad6a16SStefano Zampini   PetscErrorCode ierr;
2204fad6a16SStefano Zampini 
2214fad6a16SStefano Zampini   PetscFunctionBegin;
2224fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2234fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
2244fad6a16SStefano Zampini   PetscFunctionReturn(0);
2254fad6a16SStefano Zampini }
2264fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
2271e6b0712SBarry Smith 
2284fad6a16SStefano Zampini #undef __FUNCT__
2290bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
2300bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
2310bdf917eSStefano Zampini {
2320bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2330bdf917eSStefano Zampini   PetscErrorCode ierr;
2340bdf917eSStefano Zampini 
2350bdf917eSStefano Zampini   PetscFunctionBegin;
2360bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
2370bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
2380bdf917eSStefano Zampini   pcbddc->NullSpace=NullSpace;
2390bdf917eSStefano Zampini   PetscFunctionReturn(0);
2400bdf917eSStefano Zampini }
2411e6b0712SBarry Smith 
2420bdf917eSStefano Zampini #undef __FUNCT__
2430bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
2440bdf917eSStefano Zampini /*@
2450bdf917eSStefano Zampini  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
2460bdf917eSStefano Zampini 
2470bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
2480bdf917eSStefano Zampini 
2490bdf917eSStefano Zampini    Input Parameters:
2500bdf917eSStefano Zampini +  pc - the preconditioning context
2510bdf917eSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned.
2520bdf917eSStefano Zampini 
2530bdf917eSStefano Zampini    Level: intermediate
2540bdf917eSStefano Zampini 
2550bdf917eSStefano Zampini    Notes:
2560bdf917eSStefano Zampini 
2570bdf917eSStefano Zampini .seealso: PCBDDC
2580bdf917eSStefano Zampini @*/
2590bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
2600bdf917eSStefano Zampini {
2610bdf917eSStefano Zampini   PetscErrorCode ierr;
2620bdf917eSStefano Zampini 
2630bdf917eSStefano Zampini   PetscFunctionBegin;
2640bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
265674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
2660bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
2670bdf917eSStefano Zampini   PetscFunctionReturn(0);
2680bdf917eSStefano Zampini }
2690bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
2701e6b0712SBarry Smith 
2710bdf917eSStefano Zampini #undef __FUNCT__
2723b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
2733b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
2743b03a366Sstefano_zampini {
2753b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2763b03a366Sstefano_zampini   PetscErrorCode ierr;
2773b03a366Sstefano_zampini 
2783b03a366Sstefano_zampini   PetscFunctionBegin;
2793b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
28036e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
28136e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
2823b03a366Sstefano_zampini   PetscFunctionReturn(0);
2833b03a366Sstefano_zampini }
2841e6b0712SBarry Smith 
2853b03a366Sstefano_zampini #undef __FUNCT__
2863b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
2873b03a366Sstefano_zampini /*@
288da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
289da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
2903b03a366Sstefano_zampini 
2913b03a366Sstefano_zampini    Not collective
2923b03a366Sstefano_zampini 
2933b03a366Sstefano_zampini    Input Parameters:
2943b03a366Sstefano_zampini +  pc - the preconditioning context
2950298fd71SBarry Smith -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL)
2963b03a366Sstefano_zampini 
2973b03a366Sstefano_zampini    Level: intermediate
2983b03a366Sstefano_zampini 
2993b03a366Sstefano_zampini    Notes:
3003b03a366Sstefano_zampini 
3013b03a366Sstefano_zampini .seealso: PCBDDC
3023b03a366Sstefano_zampini @*/
3033b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
3043b03a366Sstefano_zampini {
3053b03a366Sstefano_zampini   PetscErrorCode ierr;
3063b03a366Sstefano_zampini 
3073b03a366Sstefano_zampini   PetscFunctionBegin;
3083b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
309674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
3103b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
3113b03a366Sstefano_zampini   PetscFunctionReturn(0);
3123b03a366Sstefano_zampini }
3133b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
3141e6b0712SBarry Smith 
3153b03a366Sstefano_zampini #undef __FUNCT__
3160c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
31753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
3180c7d97c5SJed Brown {
3190c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
32053cdbc3dSStefano Zampini   PetscErrorCode ierr;
3210c7d97c5SJed Brown 
3220c7d97c5SJed Brown   PetscFunctionBegin;
32353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
32436e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
32536e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
3260c7d97c5SJed Brown   PetscFunctionReturn(0);
3270c7d97c5SJed Brown }
3281e6b0712SBarry Smith 
3290c7d97c5SJed Brown #undef __FUNCT__
3300c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
33157527edcSJed Brown /*@
332da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
333da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
33457527edcSJed Brown 
3359c0446d6SStefano Zampini    Not collective
33657527edcSJed Brown 
33757527edcSJed Brown    Input Parameters:
33857527edcSJed Brown +  pc - the preconditioning context
3390298fd71SBarry Smith -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL)
34057527edcSJed Brown 
34157527edcSJed Brown    Level: intermediate
34257527edcSJed Brown 
34357527edcSJed Brown    Notes:
34457527edcSJed Brown 
34557527edcSJed Brown .seealso: PCBDDC
34657527edcSJed Brown @*/
34753cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
3480c7d97c5SJed Brown {
3490c7d97c5SJed Brown   PetscErrorCode ierr;
3500c7d97c5SJed Brown 
3510c7d97c5SJed Brown   PetscFunctionBegin;
3520c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
353674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
35453cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
35553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
35653cdbc3dSStefano Zampini }
35753cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
3581e6b0712SBarry Smith 
35953cdbc3dSStefano Zampini #undef __FUNCT__
360da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
361da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
362da1bb401SStefano Zampini {
363da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
364da1bb401SStefano Zampini 
365da1bb401SStefano Zampini   PetscFunctionBegin;
366da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
367da1bb401SStefano Zampini   PetscFunctionReturn(0);
368da1bb401SStefano Zampini }
3691e6b0712SBarry Smith 
370da1bb401SStefano Zampini #undef __FUNCT__
371da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
372da1bb401SStefano Zampini /*@
373da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
374da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
375da1bb401SStefano Zampini 
376da1bb401SStefano Zampini    Not collective
377da1bb401SStefano Zampini 
378da1bb401SStefano Zampini    Input Parameters:
379da1bb401SStefano Zampini +  pc - the preconditioning context
380da1bb401SStefano Zampini 
381da1bb401SStefano Zampini    Output Parameters:
382da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
383da1bb401SStefano Zampini 
384da1bb401SStefano Zampini    Level: intermediate
385da1bb401SStefano Zampini 
386da1bb401SStefano Zampini    Notes:
387da1bb401SStefano Zampini 
388da1bb401SStefano Zampini .seealso: PCBDDC
389da1bb401SStefano Zampini @*/
390da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
391da1bb401SStefano Zampini {
392da1bb401SStefano Zampini   PetscErrorCode ierr;
393da1bb401SStefano Zampini 
394da1bb401SStefano Zampini   PetscFunctionBegin;
395da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
396da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
397da1bb401SStefano Zampini   PetscFunctionReturn(0);
398da1bb401SStefano Zampini }
399da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
4001e6b0712SBarry Smith 
401da1bb401SStefano Zampini #undef __FUNCT__
40253cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
40353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
40453cdbc3dSStefano Zampini {
40553cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
40653cdbc3dSStefano Zampini 
40753cdbc3dSStefano Zampini   PetscFunctionBegin;
40853cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
40953cdbc3dSStefano Zampini   PetscFunctionReturn(0);
41053cdbc3dSStefano Zampini }
4111e6b0712SBarry Smith 
41253cdbc3dSStefano Zampini #undef __FUNCT__
41353cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
41453cdbc3dSStefano Zampini /*@
415da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
416da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
41753cdbc3dSStefano Zampini 
4189c0446d6SStefano Zampini    Not collective
41953cdbc3dSStefano Zampini 
42053cdbc3dSStefano Zampini    Input Parameters:
42153cdbc3dSStefano Zampini +  pc - the preconditioning context
42253cdbc3dSStefano Zampini 
42353cdbc3dSStefano Zampini    Output Parameters:
42453cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
42553cdbc3dSStefano Zampini 
42653cdbc3dSStefano Zampini    Level: intermediate
42753cdbc3dSStefano Zampini 
42853cdbc3dSStefano Zampini    Notes:
42953cdbc3dSStefano Zampini 
43053cdbc3dSStefano Zampini .seealso: PCBDDC
43153cdbc3dSStefano Zampini @*/
43253cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
43353cdbc3dSStefano Zampini {
43453cdbc3dSStefano Zampini   PetscErrorCode ierr;
43553cdbc3dSStefano Zampini 
43653cdbc3dSStefano Zampini   PetscFunctionBegin;
43753cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43853cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
4390c7d97c5SJed Brown   PetscFunctionReturn(0);
4400c7d97c5SJed Brown }
44136e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
4421e6b0712SBarry Smith 
44336e030ebSStefano Zampini #undef __FUNCT__
444da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
4451a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
44636e030ebSStefano Zampini {
44736e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
448da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
449da1bb401SStefano Zampini   PetscErrorCode ierr;
45036e030ebSStefano Zampini 
45136e030ebSStefano Zampini   PetscFunctionBegin;
452674ae819SStefano Zampini   /* free old CSR */
453674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
454674ae819SStefano Zampini   /* get CSR into graph structure */
455da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
456674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
457674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
460da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4611a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4621a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
463674ae819SStefano Zampini   }
464575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46536e030ebSStefano Zampini   PetscFunctionReturn(0);
46636e030ebSStefano Zampini }
4671e6b0712SBarry Smith 
46836e030ebSStefano Zampini #undef __FUNCT__
469da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
47036e030ebSStefano Zampini /*@
471da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47236e030ebSStefano Zampini 
47336e030ebSStefano Zampini    Not collective
47436e030ebSStefano Zampini 
47536e030ebSStefano Zampini    Input Parameters:
47636e030ebSStefano Zampini +  pc - the preconditioning context
477da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
478da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
479da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
480da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48136e030ebSStefano Zampini 
48236e030ebSStefano Zampini    Level: intermediate
48336e030ebSStefano Zampini 
48436e030ebSStefano Zampini    Notes:
48536e030ebSStefano Zampini 
48636e030ebSStefano Zampini .seealso: PCBDDC
48736e030ebSStefano Zampini @*/
4881a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
48936e030ebSStefano Zampini {
490575ad6abSStefano Zampini   void (*f)(void) = 0;
49136e030ebSStefano Zampini   PetscErrorCode ierr;
49236e030ebSStefano Zampini 
49336e030ebSStefano Zampini   PetscFunctionBegin;
49436e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
495674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
496674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
497674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
498674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
499da1bb401SStefano Zampini   }
50036e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
501575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
502575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
503575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
504575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
505575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50636e030ebSStefano Zampini   }
50736e030ebSStefano Zampini   PetscFunctionReturn(0);
50836e030ebSStefano Zampini }
5099c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5101e6b0712SBarry Smith 
5119c0446d6SStefano Zampini #undef __FUNCT__
5129c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5139c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5149c0446d6SStefano Zampini {
5159c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5169c0446d6SStefano Zampini   PetscInt i;
5179c0446d6SStefano Zampini   PetscErrorCode ierr;
5189c0446d6SStefano Zampini 
5199c0446d6SStefano Zampini   PetscFunctionBegin;
520da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5219c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5229c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5239c0446d6SStefano Zampini   }
524d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
525da1bb401SStefano Zampini   /* allocate space then set */
5269c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5279c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
528da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
529da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5309c0446d6SStefano Zampini   }
5319c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5329c0446d6SStefano Zampini   PetscFunctionReturn(0);
5339c0446d6SStefano Zampini }
5341e6b0712SBarry Smith 
5359c0446d6SStefano Zampini #undef __FUNCT__
5369c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5379c0446d6SStefano Zampini /*@
538da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5399c0446d6SStefano Zampini 
5409c0446d6SStefano Zampini    Not collective
5419c0446d6SStefano Zampini 
5429c0446d6SStefano Zampini    Input Parameters:
5439c0446d6SStefano Zampini +  pc - the preconditioning context
544da1bb401SStefano Zampini -  n - number of index sets defining the fields
545da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5469c0446d6SStefano Zampini 
5479c0446d6SStefano Zampini    Level: intermediate
5489c0446d6SStefano Zampini 
5499c0446d6SStefano Zampini    Notes:
5509c0446d6SStefano Zampini 
5519c0446d6SStefano Zampini .seealso: PCBDDC
5529c0446d6SStefano Zampini @*/
5539c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5549c0446d6SStefano Zampini {
5559c0446d6SStefano Zampini   PetscErrorCode ierr;
5569c0446d6SStefano Zampini 
5579c0446d6SStefano Zampini   PetscFunctionBegin;
5589c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5599c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5609c0446d6SStefano Zampini   PetscFunctionReturn(0);
5619c0446d6SStefano Zampini }
562da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
563534831adSStefano Zampini #undef __FUNCT__
564534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
565534831adSStefano Zampini /* -------------------------------------------------------------------------- */
566534831adSStefano Zampini /*
567534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
568534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5699c0446d6SStefano Zampini 
570534831adSStefano Zampini    Input Parameter:
571534831adSStefano Zampini +  pc - the preconditioner contex
572534831adSStefano Zampini 
573534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
574534831adSStefano Zampini 
575534831adSStefano Zampini    Notes:
576534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
577534831adSStefano Zampini    the user, but instead is called by KSPSolve().
578534831adSStefano Zampini */
579534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
580534831adSStefano Zampini {
581534831adSStefano Zampini   PetscErrorCode ierr;
582534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
583534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
584534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
585534831adSStefano Zampini   Mat            temp_mat;
5863972b0daSStefano Zampini   IS             dirIS;
5873972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5883972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5893972b0daSStefano Zampini   Vec            used_vec;
5903972b0daSStefano Zampini   PetscBool      guess_nonzero;
591534831adSStefano Zampini 
592534831adSStefano Zampini   PetscFunctionBegin;
5933972b0daSStefano Zampini   if (x) {
5943972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
5953972b0daSStefano Zampini     used_vec = x;
5963972b0daSStefano Zampini   } else {
5973972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
5983972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
5993972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6003972b0daSStefano Zampini   }
6013972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6023972b0daSStefano Zampini   if (ksp) {
6033972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6043972b0daSStefano Zampini     if ( !guess_nonzero ) {
6053972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6063972b0daSStefano Zampini     }
6073972b0daSStefano Zampini   }
6083972b0daSStefano Zampini   /* store the original rhs */
6093972b0daSStefano Zampini   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6103972b0daSStefano Zampini 
6113972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
6123972b0daSStefano Zampini   ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6133972b0daSStefano Zampini   ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6143972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6153972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6163972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6173972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6183972b0daSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6193972b0daSStefano Zampini   if (dirIS) {
6203972b0daSStefano Zampini     ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6213972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6223972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6233972b0daSStefano Zampini     ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6242fa5cd67SKarl Rupp     for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6253972b0daSStefano Zampini     ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6263972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6273972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6283972b0daSStefano Zampini   }
6293972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6303972b0daSStefano Zampini   ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
631b76ba322SStefano Zampini 
6323972b0daSStefano Zampini   /* remove the computed solution from the rhs */
6333972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6343972b0daSStefano Zampini   ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6353972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
636b76ba322SStefano Zampini 
637b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6383972b0daSStefano Zampini   if (x) {
6393972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6403972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
64115aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
642b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
643b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
644b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
645b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
646b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
647b76ba322SStefano Zampini       if (ksp) {
648b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
649b76ba322SStefano Zampini       }
650b76ba322SStefano Zampini     }
6513972b0daSStefano Zampini   }
652b76ba322SStefano Zampini 
653b76ba322SStefano Zampini   /* rhs change of basis */
654674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
655b76ba322SStefano Zampini     /* swap pointers for local matrices */
656b76ba322SStefano Zampini     temp_mat = matis->A;
657b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
658b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
659b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
660b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
661b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
662b76ba322SStefano Zampini     /* from original basis to modified basis */
663b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
664b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
665b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
666b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
667674ae819SStefano Zampini   }
6680bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
669d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
670d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
671b76ba322SStefano Zampini   }
6720bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
673534831adSStefano Zampini   PetscFunctionReturn(0);
674534831adSStefano Zampini }
675534831adSStefano Zampini /* -------------------------------------------------------------------------- */
676534831adSStefano Zampini #undef __FUNCT__
677534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
678534831adSStefano Zampini /* -------------------------------------------------------------------------- */
679534831adSStefano Zampini /*
680534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
681534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
682534831adSStefano Zampini 
683534831adSStefano Zampini    Input Parameter:
684534831adSStefano Zampini +  pc - the preconditioner contex
685534831adSStefano Zampini 
686534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
687534831adSStefano Zampini 
688534831adSStefano Zampini    Notes:
689534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
690534831adSStefano Zampini    the user, but instead is called by KSPSolve().
691534831adSStefano Zampini */
692534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
693534831adSStefano Zampini {
694534831adSStefano Zampini   PetscErrorCode ierr;
695534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
696534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
697534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
698534831adSStefano Zampini   Mat            temp_mat;
699534831adSStefano Zampini 
700534831adSStefano Zampini   PetscFunctionBegin;
701674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
702534831adSStefano Zampini     /* swap pointers for local matrices */
703534831adSStefano Zampini     temp_mat = matis->A;
704534831adSStefano Zampini     matis->A = pcbddc->local_mat;
705534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
706534831adSStefano Zampini     /* restore rhs to its original state */
7073425bc38SStefano Zampini     if (rhs) {
7083425bc38SStefano Zampini       ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
7093425bc38SStefano Zampini     }
710534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
711534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
712534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
713534831adSStefano Zampini     /* from modified basis to original basis */
714534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
715534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
716534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
717534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
718534831adSStefano Zampini   }
7193972b0daSStefano Zampini   /* add solution removed in presolve */
7203425bc38SStefano Zampini   if (x) {
7213425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7223425bc38SStefano Zampini   }
723534831adSStefano Zampini   PetscFunctionReturn(0);
724534831adSStefano Zampini }
725534831adSStefano Zampini /* -------------------------------------------------------------------------- */
72653cdbc3dSStefano Zampini #undef __FUNCT__
72753cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7280c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7290c7d97c5SJed Brown /*
7300c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7310c7d97c5SJed Brown                   by setting data structures and options.
7320c7d97c5SJed Brown 
7330c7d97c5SJed Brown    Input Parameter:
73453cdbc3dSStefano Zampini +  pc - the preconditioner context
7350c7d97c5SJed Brown 
7360c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7370c7d97c5SJed Brown 
7380c7d97c5SJed Brown    Notes:
7390c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7400c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7410c7d97c5SJed Brown */
74253cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7430c7d97c5SJed Brown {
7440c7d97c5SJed Brown   PetscErrorCode ierr;
7450c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
746674ae819SStefano Zampini   MatStructure   flag;
747674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7480c7d97c5SJed Brown 
7490c7d97c5SJed Brown   PetscFunctionBegin;
750674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7513b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7529c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7530c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7540c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7550c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7563b03a366Sstefano_zampini   /* Get stdout for dbg */
757674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
758ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
759e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
760e269702eSStefano Zampini   }
761674ae819SStefano Zampini   /* first attempt to split work */
762674ae819SStefano Zampini   if (pc->setupcalled) {
763674ae819SStefano Zampini     computeis = PETSC_FALSE;
764674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
765674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
766674ae819SStefano Zampini       computetopography = PETSC_FALSE;
767674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
768674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
769674ae819SStefano Zampini       computetopography = PETSC_FALSE;
770674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
771674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
772674ae819SStefano Zampini       computetopography = PETSC_TRUE;
773674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
774674ae819SStefano Zampini     }
775674ae819SStefano Zampini   } else {
776674ae819SStefano Zampini     computeis = PETSC_TRUE;
777674ae819SStefano Zampini     computetopography = PETSC_TRUE;
778674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
779674ae819SStefano Zampini   }
780674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
781674ae819SStefano Zampini   if (computeis) {
782674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
783674ae819SStefano Zampini   }
784674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
785674ae819SStefano Zampini   if (computetopography) {
786674ae819SStefano Zampini     /* reset data */
787674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
788674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
789674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
790674ae819SStefano Zampini   }
791674ae819SStefano Zampini   if (computesolvers) {
792674ae819SStefano Zampini     /* reset data */
793674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
794674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
7950c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
7960c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
797674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
7980c7d97c5SJed Brown   }
7990c7d97c5SJed Brown   PetscFunctionReturn(0);
8000c7d97c5SJed Brown }
8010c7d97c5SJed Brown 
8020c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8030c7d97c5SJed Brown /*
8040c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8050c7d97c5SJed Brown 
8060c7d97c5SJed Brown    Input Parameters:
8070c7d97c5SJed Brown .  pc - the preconditioner context
8080c7d97c5SJed Brown .  r - input vector (global)
8090c7d97c5SJed Brown 
8100c7d97c5SJed Brown    Output Parameter:
8110c7d97c5SJed Brown .  z - output vector (global)
8120c7d97c5SJed Brown 
8130c7d97c5SJed Brown    Application Interface Routine: PCApply()
8140c7d97c5SJed Brown  */
8150c7d97c5SJed Brown #undef __FUNCT__
8160c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
81753cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8180c7d97c5SJed Brown {
8190c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8200c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8210c7d97c5SJed Brown   PetscErrorCode    ierr;
8223b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8233b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8242617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8250c7d97c5SJed Brown 
8260c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8270c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
82829622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8290c7d97c5SJed Brown 
8300c7d97c5SJed Brown   PetscFunctionBegin;
83115aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8320c7d97c5SJed Brown     /* First Dirichlet solve */
8330c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8340c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
83553cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8360c7d97c5SJed Brown     /*
8370c7d97c5SJed Brown       Assembling right hand side for BDDC operator
838674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
839674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8400c7d97c5SJed Brown     */
8410c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8420c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
84329622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8440c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8450c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8460c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8470c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
848674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
849b76ba322SStefano Zampini   } else {
8500bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
851b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
852674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
853b76ba322SStefano Zampini   }
854b76ba322SStefano Zampini 
8552617d88aSStefano Zampini   /* Apply interface preconditioner
8562617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8572617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8582617d88aSStefano Zampini 
859674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
860674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8610c7d97c5SJed Brown 
8623b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8630c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8640c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8650c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
86629622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
86753cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8680c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
86929622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8700c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8710c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8720c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8730c7d97c5SJed Brown   PetscFunctionReturn(0);
8740c7d97c5SJed Brown }
875da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
876674ae819SStefano Zampini 
877da1bb401SStefano Zampini #undef __FUNCT__
878da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
879da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
880da1bb401SStefano Zampini {
881da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
882da1bb401SStefano Zampini   PetscErrorCode ierr;
883da1bb401SStefano Zampini 
884da1bb401SStefano Zampini   PetscFunctionBegin;
885da1bb401SStefano Zampini   /* free data created by PCIS */
886da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
887674ae819SStefano Zampini   /* free BDDC custom data  */
888674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
889674ae819SStefano Zampini   /* destroy objects related to topography */
890674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
891674ae819SStefano Zampini   /* free allocated graph structure */
892da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
893674ae819SStefano Zampini   /* free data for scaling operator */
894674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
895674ae819SStefano Zampini   /* free solvers stuff */
896674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
89733bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
89833bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
899ac78edfcSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);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__
12774fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12784fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12794fad6a16SStefano Zampini {
12804fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12814fad6a16SStefano Zampini 
12824fad6a16SStefano Zampini   PetscFunctionBegin;
12834fad6a16SStefano Zampini   pcbddc->current_level=level;
12844fad6a16SStefano Zampini   PetscFunctionReturn(0);
12854fad6a16SStefano Zampini }
12863425bc38SStefano Zampini 
12873b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
12880c7d97c5SJed Brown #undef __FUNCT__
12890c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
129053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
12910c7d97c5SJed Brown {
12920c7d97c5SJed Brown   PetscErrorCode  ierr;
1293674ae819SStefano Zampini 
12940c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
12950c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
12960c7d97c5SJed Brown   IS                is_R_local;
129719fd82e9SBarry Smith   VecType           impVecType;
129819fd82e9SBarry Smith   MatType           impMatType;
12990c7d97c5SJed Brown   PetscInt          n_R=0;
13000c7d97c5SJed Brown   PetscInt          n_D=0;
13010c7d97c5SJed Brown   PetscInt          n_B=0;
13020c7d97c5SJed Brown   PetscScalar       zero=0.0;
13030c7d97c5SJed Brown   PetscScalar       one=1.0;
13040c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
13050c7d97c5SJed Brown   PetscScalar*      array;
13060c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
13070c7d97c5SJed Brown   PetscInt          *idx_R_local;
13085b08dc53SStefano Zampini   PetscReal         *coarsefunctions_errors,*constraints_errors;
13090c7d97c5SJed Brown   /* auxiliary indices */
1310*aa0d41d4SStefano Zampini   PetscInt          i,j;
1311e269702eSStefano Zampini   /* for verbose output of bddc */
1312e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
13135b08dc53SStefano Zampini   PetscInt          dbg_flag=pcbddc->dbg_flag;
1314a0ba757dSStefano Zampini   /* for counting coarse dofs */
1315534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
13163b03a366Sstefano_zampini   PetscInt          size_of_constraint;
13173b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
13183b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1319e6872a76SStefano Zampini   PetscInt          *vertices;
13200c7d97c5SJed Brown 
13210c7d97c5SJed Brown   PetscFunctionBegin;
13220c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
13230c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
1324534831adSStefano Zampini 
1325*aa0d41d4SStefano Zampini   /* compute matrix after change of basis and extract local submatrices */
1326*aa0d41d4SStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
1327ac78edfcSStefano Zampini 
1328674ae819SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1329674ae819SStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1330674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
13310bdf917eSStefano Zampini   }
1332a0ba757dSStefano Zampini 
1333e6872a76SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
1334e6872a76SStefano Zampini   impMatType = MATSEQDENSE;
1335e6872a76SStefano Zampini   impVecType = VECSEQ;
1336e6872a76SStefano Zampini   /* get vertex indices from constraint matrix */
1337e6872a76SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1338e6872a76SStefano Zampini   /* Set number of constraints */
1339e6872a76SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
13400c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
13410c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
13420c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13432fa5cd67SKarl Rupp   for (i=0;i<n_vertices;i++) array[vertices[i]] = zero;
13443b03a366Sstefano_zampini   ierr = PetscMalloc((pcis->n-n_vertices)*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
13452fa5cd67SKarl Rupp   for (i=0, n_R=0; i<pcis->n; i++) {
13462fa5cd67SKarl Rupp     if (array[i] == one) {
13472fa5cd67SKarl Rupp       idx_R_local[n_R] = i;
13482fa5cd67SKarl Rupp       n_R++;
13492fa5cd67SKarl Rupp     }
13502fa5cd67SKarl Rupp   }
13510c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1352e6872a76SStefano Zampini   ierr = PetscFree(vertices);CHKERRQ(ierr);
1353e269702eSStefano Zampini   if (dbg_flag) {
13540c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13550c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13560c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
13570c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
13583b03a366Sstefano_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);
1359534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
13600c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13610c7d97c5SJed Brown   }
1362534831adSStefano Zampini 
13630c7d97c5SJed Brown   /* Allocate needed vectors */
1364534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
13653972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
13660c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
13670c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
13680c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
13690c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1370d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
13710c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
13720c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
13730c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
13740c7d97c5SJed Brown 
13750c7d97c5SJed Brown   /* Creating some index sets needed  */
13760c7d97c5SJed Brown   /* For submatrices */
1377da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
1378da1bb401SStefano Zampini 
13790c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
13800c7d97c5SJed Brown   {
1381e6872a76SStefano Zampini     IS         is_aux1,is_aux2;
13820c7d97c5SJed Brown     PetscInt   *aux_array1;
13830c7d97c5SJed Brown     PetscInt   *aux_array2;
13842e8d2280SStefano Zampini     PetscInt   *idx_I_local;
13850c7d97c5SJed Brown 
13863b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
13873b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
13880c7d97c5SJed Brown 
13892e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
13900c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13912fa5cd67SKarl Rupp     for (i=0; i<n_D; i++) array[idx_I_local[i]] = 0;
13922e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
13932fa5cd67SKarl Rupp     for (i=0, j=0; i<n_R; i++) {
13942fa5cd67SKarl Rupp       if (array[idx_R_local[i]] == one) {
13952fa5cd67SKarl Rupp         aux_array1[j] = i;
13962fa5cd67SKarl Rupp         j++;
13972fa5cd67SKarl Rupp       }
13982fa5cd67SKarl Rupp     }
13990c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1400da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
14012e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14022e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14030c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
14042fa5cd67SKarl Rupp     for (i=0, j=0; i<n_B; i++) {
14052fa5cd67SKarl Rupp       if (array[i] == one) {
14062fa5cd67SKarl Rupp         aux_array2[j] = i; j++;
14072fa5cd67SKarl Rupp       }
14082fa5cd67SKarl Rupp     }
14093828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1410da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
14110c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
14120c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
14130c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
14140c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14150c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
14160c7d97c5SJed Brown 
141729622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
14180c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
14190c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14202fa5cd67SKarl Rupp       for (i=0, j=0; i<n_R; i++) {
14212fa5cd67SKarl Rupp         if (array[idx_R_local[i]] == zero) {
14222fa5cd67SKarl Rupp           aux_array1[j] = i;
14232fa5cd67SKarl Rupp           j++;
14242fa5cd67SKarl Rupp         }
14252fa5cd67SKarl Rupp       }
14260c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1427da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
14280c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
14290c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
14300c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14310c7d97c5SJed Brown     }
14320c7d97c5SJed Brown   }
14330c7d97c5SJed Brown 
1434304d26faSStefano Zampini   /* setup local solvers */
1435304d26faSStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,pcis->is_I_local,is_R_local);CHKERRQ(ierr);
14360c7d97c5SJed Brown 
14370c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
14380c7d97c5SJed Brown   {
14390c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
14400bdf917eSStefano Zampini     Mat          M1;
14410c7d97c5SJed Brown     Mat          C_CR;
14423b03a366Sstefano_zampini     Mat          AUXMAT;
14430c7d97c5SJed Brown     Vec          vec1_C;
14440c7d97c5SJed Brown     Vec          vec2_C;
14450c7d97c5SJed Brown     Vec          vec1_V;
14460c7d97c5SJed Brown     Vec          vec2_V;
1447e6872a76SStefano Zampini     IS           is_C_local,is_V_local,is_aux1;
1448e6872a76SStefano Zampini     ISLocalToGlobalMapping BtoNmap;
14490c7d97c5SJed Brown     PetscInt     *nnz;
1450e6872a76SStefano Zampini     PetscInt     *idx_V_B;
14510c7d97c5SJed Brown     PetscInt     *auxindices;
145253cdbc3dSStefano Zampini     PetscInt     index;
14530c7d97c5SJed Brown     PetscScalar* array2;
14540c7d97c5SJed Brown     MatFactorInfo matinfo;
145515aaf578SStefano Zampini     PetscBool    setsym=PETSC_FALSE,issym=PETSC_FALSE;
14560c7d97c5SJed Brown 
14570c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
14580c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
14590c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
14602fa5cd67SKarl Rupp     for (i=0;i<pcis->n;i++) auxindices[i]=i;
14610c7d97c5SJed Brown 
1462e6872a76SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1463e6872a76SStefano Zampini     /* vertices in boundary numbering */
1464e6872a76SStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1465e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
1466e6872a76SStefano Zampini     ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
1467e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
1468e6872a76SStefano Zampini     if (i != n_vertices) {
1469e6872a76SStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1470e6872a76SStefano Zampini     }
1471e6872a76SStefano Zampini 
14720c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
14733b03a366Sstefano_zampini     if (n_vertices) {
14740c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
14753b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
14760c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
14770c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
14780c7d97c5SJed Brown     }
1479534831adSStefano Zampini     if (n_constraints) {
14800c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
1481534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
14820c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
14830c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
14840c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
14850c7d97c5SJed Brown     }
14860c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14873b03a366Sstefano_zampini     if (n_constraints) {
14880c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14893b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14900c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14910298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,NULL);CHKERRQ(ierr);
14920c7d97c5SJed Brown 
149357a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
1494e6872a76SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
149557a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
149657a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
149757a90decSStefano Zampini 
14980c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14993b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
15003b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
15013b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
150257a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
150357a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
15042fa5cd67SKarl Rupp         for (j=0;j<size_of_constraint;j++) array[row_cmat_indices[j]] = -row_cmat_values[j];
150557a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
150657a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
15072fa5cd67SKarl Rupp 
15083b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
150953cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
15102fa5cd67SKarl Rupp 
15113b03a366Sstefano_zampini         /* Set values */
15120c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15133b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15140c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15150c7d97c5SJed Brown       }
15160c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15170c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15180c7d97c5SJed Brown 
15190c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
15200c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1521d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
15223b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
15230c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
15240c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
15250c7d97c5SJed Brown 
15263b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1527d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
15283b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
15290c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
15300298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(M1,NULL);CHKERRQ(ierr);
15313b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
15320c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
15330c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
15340c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
15350c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
15360c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
15370c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
15380c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
15393b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15400c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
15410c7d97c5SJed Brown       }
15420c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15430c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15440c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
15450c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
15460c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
15470c7d97c5SJed Brown 
15480c7d97c5SJed Brown     }
15490c7d97c5SJed Brown 
15500c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
15513b03a366Sstefano_zampini     if (n_vertices) {
155215aaf578SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr);
1553534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1554534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1555534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
155615aaf578SStefano Zampini       ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
15570c7d97c5SJed Brown     }
15580c7d97c5SJed Brown 
15590c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1560d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
15610c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
15620c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
15630298fd71SBarry Smith     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,NULL);CHKERRQ(ierr);
156429622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
1565d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
15660c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
15670c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
15680298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,NULL);CHKERRQ(ierr);
15690c7d97c5SJed Brown     }
15700c7d97c5SJed Brown 
1571e269702eSStefano Zampini     if (dbg_flag) {
15725b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*coarsefunctions_errors),&coarsefunctions_errors);CHKERRQ(ierr);
15735b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*constraints_errors),&constraints_errors);CHKERRQ(ierr);
15740c7d97c5SJed Brown     }
15753b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15760c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15770c7d97c5SJed Brown 
15780c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15793b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++){
15800c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15810c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15820c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15830c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15840c7d97c5SJed Brown       /* solution of saddle point problem */
15850bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15860bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15870c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15883b03a366Sstefano_zampini       if (n_constraints) {
15890c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15900c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15910c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15920c7d97c5SJed Brown       }
15930c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15940c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15950c7d97c5SJed Brown 
15960c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15970c7d97c5SJed Brown       /* coarse basis functions */
15980c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15990c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16000c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16010c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
16023b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
16030c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
16040c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
160529622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag  ) {
16060c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16070c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16080c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16093b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
16100c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16110c7d97c5SJed Brown       }
16120c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16130c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16142fa5cd67SKarl Rupp       for (j=0; j<n_vertices; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j];   /* WARNING -> column major ordering */
16150c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16163b03a366Sstefano_zampini       if (n_constraints) {
16170c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16182fa5cd67SKarl 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 */
16190c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16200c7d97c5SJed Brown       }
16210c7d97c5SJed Brown 
1622e269702eSStefano Zampini       if ( dbg_flag ) {
16230c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1624d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16250c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16260c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16272fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
16283b03a366Sstefano_zampini         array[ vertices[i] ] = one;
16290c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16300c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16310c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1632d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16330c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16340c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16352fa5cd67SKarl Rupp         for (j=0;j<n_vertices;j++) array2[j]=array[j];
16360c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16373b03a366Sstefano_zampini         if (n_constraints) {
16380c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16392fa5cd67SKarl Rupp           for (j=0;j<n_constraints;j++) array2[j+n_vertices]=array[j];
16400c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16410c7d97c5SJed Brown         }
16420c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16430c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
16440c7d97c5SJed Brown         /* check saddle point solution */
1645534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16463b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
16473b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
16483b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16490c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16503b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
16510c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16523b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
16530c7d97c5SJed Brown       }
16540c7d97c5SJed Brown     }
16550c7d97c5SJed Brown 
16563b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++){
1657d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
16580c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
16590c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
16600c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
16610c7d97c5SJed Brown       /* solution of saddle point problem */
16620c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
16630c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
16640c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
16653b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
16660c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
16670c7d97c5SJed Brown       /* coarse basis functions */
16683b03a366Sstefano_zampini       index=i+n_vertices;
16690c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
16700c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16710c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16720c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
167353cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16740c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
167529622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
16760c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16770c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16780c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
167953cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16800c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16810c7d97c5SJed Brown       }
16820c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16833b03a366Sstefano_zampini       if (n_vertices) {
16840c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16852fa5cd67SKarl Rupp         for (j=0; j<n_vertices; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j]; /* WARNING -> column major ordering */
16860c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16870c7d97c5SJed Brown       }
16880c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16892fa5cd67SKarl 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 */
16900c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16910c7d97c5SJed Brown 
1692e269702eSStefano Zampini       if ( dbg_flag ) {
16930c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
169453cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16950c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16960c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16972fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
16980c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16990c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
17000c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
170153cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
17020c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
17033b03a366Sstefano_zampini         if ( n_vertices) {
17040c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
17052fa5cd67SKarl Rupp           for (j=0;j<n_vertices;j++) array2[j]=-array[j];
17060c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
17070c7d97c5SJed Brown         }
17080c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
17093b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
17100c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
17110c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
17123972b0daSStefano Zampini         /* check saddle point solution */
1713534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
17143b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
171553cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
17163b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
17170c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
171853cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
17190c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
172053cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
17210c7d97c5SJed Brown       }
17220c7d97c5SJed Brown     }
17230c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17240c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
172529622bf0SStefano Zampini     if ( pcbddc->inexact_prec_type || dbg_flag ) {
17260c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17270c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17280c7d97c5SJed Brown     }
172915aaf578SStefano Zampini     /* compute other basis functions for non-symmetric problems */
173015aaf578SStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
173115aaf578SStefano Zampini     if ( !setsym || (setsym && !issym) ) {
173215aaf578SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
173315aaf578SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
173415aaf578SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
173515aaf578SStefano Zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_B,NULL);CHKERRQ(ierr);
173615aaf578SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag ) {
173715aaf578SStefano Zampini         ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
173815aaf578SStefano Zampini         ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
173915aaf578SStefano Zampini         ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
174015aaf578SStefano Zampini         ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_D,NULL);CHKERRQ(ierr);
174115aaf578SStefano Zampini       }
174215aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
174315aaf578SStefano Zampini         if (n_constraints) {
174415aaf578SStefano Zampini           ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
174515aaf578SStefano Zampini           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
174615aaf578SStefano Zampini           for (j=0;j<n_constraints;j++) {
174715aaf578SStefano Zampini             array[j]=coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i];
174815aaf578SStefano Zampini           }
174915aaf578SStefano Zampini           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
175015aaf578SStefano Zampini         }
175115aaf578SStefano Zampini         if (i<n_vertices) {
175215aaf578SStefano Zampini           ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
175315aaf578SStefano Zampini           ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
175415aaf578SStefano Zampini           ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
175515aaf578SStefano Zampini           ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
175615aaf578SStefano Zampini           ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
175715aaf578SStefano Zampini           if (n_constraints) {
175815aaf578SStefano Zampini             ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
175915aaf578SStefano Zampini           }
176015aaf578SStefano Zampini         } else {
176115aaf578SStefano Zampini           ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
176215aaf578SStefano Zampini         }
176315aaf578SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
176415aaf578SStefano Zampini         ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
176515aaf578SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
176615aaf578SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
176715aaf578SStefano Zampini         ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
176815aaf578SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
176915aaf578SStefano Zampini         ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
177015aaf578SStefano Zampini         if (i<n_vertices) {
177115aaf578SStefano Zampini           ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
177215aaf578SStefano Zampini         }
177315aaf578SStefano Zampini         if ( pcbddc->inexact_prec_type || dbg_flag  ) {
177415aaf578SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177515aaf578SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177615aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
177715aaf578SStefano Zampini           ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
177815aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
177915aaf578SStefano Zampini         }
178015aaf578SStefano Zampini 
178115aaf578SStefano Zampini         if ( dbg_flag ) {
178215aaf578SStefano Zampini           /* assemble subdomain vector on nodes */
178315aaf578SStefano Zampini           ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
178415aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
178515aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
178615aaf578SStefano Zampini           for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
178715aaf578SStefano Zampini           if (i<n_vertices) array[vertices[i]] = one;
178815aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
178915aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
179015aaf578SStefano Zampini           /* assemble subdomain vector of lagrange multipliers */
179115aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
179215aaf578SStefano Zampini           for (j=0;j<pcbddc->local_primal_size;j++) {
179315aaf578SStefano Zampini             array[j]=-coarse_submat_vals[j*pcbddc->local_primal_size+i];
179415aaf578SStefano Zampini           }
179515aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
179615aaf578SStefano Zampini           /* check saddle point solution */
179715aaf578SStefano Zampini           ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
179815aaf578SStefano Zampini           ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
179915aaf578SStefano Zampini           ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
180015aaf578SStefano Zampini           ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
180115aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
180215aaf578SStefano Zampini           array[i]=array[i]+m_one; /* shift by the identity matrix */
180315aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
180415aaf578SStefano Zampini           ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
180515aaf578SStefano Zampini         }
180615aaf578SStefano Zampini       }
180715aaf578SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180815aaf578SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180915aaf578SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
181015aaf578SStefano Zampini         ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181115aaf578SStefano Zampini         ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181215aaf578SStefano Zampini       }
181315aaf578SStefano Zampini     }
181415aaf578SStefano Zampini     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
18150c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
181615aaf578SStefano Zampini     /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
181715aaf578SStefano Zampini     /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
18189d2fce94SStefano Zampini     if (dbg_flag) {
18190c7d97c5SJed Brown       Mat         coarse_sub_mat;
18200c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
182115aaf578SStefano Zampini       Mat         coarse_phi_D,coarse_phi_B;
182215aaf578SStefano Zampini       Mat         coarse_psi_D,coarse_psi_B;
182315aaf578SStefano Zampini       Mat         A_II,A_BB,A_IB,A_BI;
182419fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
18255b08dc53SStefano Zampini       PetscReal   real_value;
18260c7d97c5SJed Brown 
1827c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1828c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1829c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1830c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1831c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1832c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
183315aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
183415aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
183515aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
183615aaf578SStefano Zampini       }
1837c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
18380c7d97c5SJed Brown 
18390c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
18400c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
18410c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
184215aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
184315aaf578SStefano Zampini         ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
184415aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
184515aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
184615aaf578SStefano Zampini         ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
184715aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
184815aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
184915aaf578SStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
185015aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
185115aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
185215aaf578SStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
185315aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
185415aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
185515aaf578SStefano Zampini       } else {
185653cdbc3dSStefano Zampini         ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
185753cdbc3dSStefano Zampini         ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
185853cdbc3dSStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1859c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
186053cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
186153cdbc3dSStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1862c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
186353cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
186415aaf578SStefano Zampini       }
186553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
186653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
186753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
186815aaf578SStefano Zampini       ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
186915aaf578SStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
18705b08dc53SStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
18710c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
18720c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
18735b08dc53SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
187415aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
187515aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
187615aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
187715aaf578SStefano Zampini       }
187815aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
187915aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
188015aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
188115aaf578SStefano Zampini       }
188215aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
188315aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
188415aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
188515aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
188615aaf578SStefano Zampini         }
188715aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
188815aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
188915aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
189015aaf578SStefano Zampini         }
189115aaf578SStefano Zampini       }
18920c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
189353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
189453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
189553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
189653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
189753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
189853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
189953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
190053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
190153cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
190253cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
190315aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
190415aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
190515aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
190615aaf578SStefano Zampini       }
190715aaf578SStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
19080c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
19090c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
19100c7d97c5SJed Brown     }
19110c7d97c5SJed Brown     /* free memory */
19123b03a366Sstefano_zampini     if (n_vertices) {
191315aaf578SStefano Zampini       ierr = PetscFree(vertices);CHKERRQ(ierr);
19140c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
19150c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
19160c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
19170c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
19180c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
19190c7d97c5SJed Brown     }
1920534831adSStefano Zampini     if (n_constraints) {
19210c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
19220c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
19230c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
19240c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
19250c7d97c5SJed Brown     }
1926a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
1927a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1928a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
1929674ae819SStefano Zampini     ierr = PCBDDCSetUpCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
1930a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
19310c7d97c5SJed Brown   }
19320c7d97c5SJed Brown   /* free memory */
19330c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1934674ae819SStefano Zampini 
19350c7d97c5SJed Brown   PetscFunctionReturn(0);
19360c7d97c5SJed Brown }
19370c7d97c5SJed Brown 
19380c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
19390c7d97c5SJed Brown 
19407cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
19417cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
19427cbb387bSStefano Zampini #include "metis.h"
19437cbb387bSStefano Zampini #define MetisInt    idx_t
19447cbb387bSStefano Zampini #define MetisScalar real_t
19457cbb387bSStefano Zampini #endif
19467cbb387bSStefano Zampini 
19470c7d97c5SJed Brown #undef __FUNCT__
1948674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
1949674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
19500c7d97c5SJed Brown {
1951674ae819SStefano Zampini 
1952674ae819SStefano Zampini 
19530c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
19540c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
19550c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1956ce94432eSBarry Smith   MPI_Comm  prec_comm;
19570c7d97c5SJed Brown   MPI_Comm  coarse_comm;
19580c7d97c5SJed Brown 
1959674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1960674ae819SStefano Zampini 
19610c7d97c5SJed Brown   /* common to all choiches */
19620c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
19630c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
19640c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
19650c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
19660c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
19670c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
19680c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
19690c7d97c5SJed Brown   PetscMPIInt master_proc=0;
19700c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
19710c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
19725b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
19730c7d97c5SJed Brown   PetscMPIInt count_recv=0;
19745b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
19750c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
19760c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
19770c7d97c5SJed Brown   /* some other variables */
19780c7d97c5SJed Brown   PetscErrorCode ierr;
197919fd82e9SBarry Smith   MatType coarse_mat_type;
198019fd82e9SBarry Smith   PCType  coarse_pc_type;
198119fd82e9SBarry Smith   KSPType coarse_ksp_type;
198253cdbc3dSStefano Zampini   PC pc_temp;
19834fad6a16SStefano Zampini   PetscInt i,j,k;
19843b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1985e269702eSStefano Zampini   /* verbose output viewer */
1986e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
19875b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
1988142dfd88SStefano Zampini 
1989ea7e1babSStefano Zampini   PetscInt      offset,offset2;
1990a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
1991523858cfSStefano Zampini   PetscInt      *dnz,*onz;
1992142dfd88SStefano Zampini 
1993142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
19940c7d97c5SJed Brown 
19950c7d97c5SJed Brown   PetscFunctionBegin;
19964b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
19970c7d97c5SJed Brown   ins_local_primal_indices = 0;
19980c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
19990c7d97c5SJed Brown   localsizes2              = 0;
20000c7d97c5SJed Brown   localdispl2              = 0;
20010c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
20020c7d97c5SJed Brown   coarse_ISLG              = 0;
20030c7d97c5SJed Brown 
200453cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
200553cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
2006142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
2007142dfd88SStefano Zampini 
2008beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
2009beed3852SStefano Zampini   {
2010674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
2011ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
2012ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
2013ef028eecSStefano Zampini 
2014ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
2015beed3852SStefano Zampini 
2016beed3852SStefano Zampini     /* Construct needed data structures for message passing */
2017ffe5efe1SStefano Zampini     j = 0;
2018142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2019ffe5efe1SStefano Zampini       j = size_prec_comm;
2020ffe5efe1SStefano Zampini     }
2021ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
2022ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2023beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
2024142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20255619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
2026ffe5efe1SStefano Zampini     } else {
2027ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
2028ffe5efe1SStefano Zampini     }
2029beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
2030ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
2031beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
2032beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
2033beed3852SStefano Zampini     }
2034beed3852SStefano Zampini 
2035da1bb401SStefano Zampini     /* First let's count coarse dofs.
2036beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
2037beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
2038beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2039ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
2040674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
2041674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
2042674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2043674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
2044674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
2045674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
2046ef028eecSStefano Zampini     /* Compute number of coarse dofs */
2047674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
2048ef028eecSStefano Zampini 
2049ef028eecSStefano Zampini     if (dbg_flag) {
20502e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20512e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
20522e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
20532e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
20542e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20552fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
2056beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20572e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2058da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2059da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2060da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2061da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2062da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20632e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
20642e8d2280SStefano Zampini         if (array[i] == 1.0) {
20652e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
20662e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
20672e8d2280SStefano Zampini         }
20682e8d2280SStefano Zampini       }
20692e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20702e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
20715b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
20722e8d2280SStefano Zampini       }
2073da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20742e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2075da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2076da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2077da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
20782e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
20792e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20802e8d2280SStefano Zampini     }
2081142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
20820bdf917eSStefano Zampini   }
20830bdf917eSStefano Zampini 
20842e8d2280SStefano Zampini   if (dbg_flag) {
20857cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
20869d9e44b6SStefano Zampini     if (dbg_flag > 1) {
2087674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
20882e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2089674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2090674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
2091674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
2092674ae819SStefano Zampini       }
20932e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20942e8d2280SStefano Zampini     }
20952e8d2280SStefano Zampini   }
20962e8d2280SStefano Zampini 
2097a929c220SStefano Zampini   im_active = 0;
20982fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
2099a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
21000bdf917eSStefano Zampini 
21010bdf917eSStefano Zampini   /* adapt coarse problem type */
21027cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
21034fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
21044fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2105a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
21060bdf917eSStefano Zampini         if (dbg_flag) {
2107a929c220SStefano 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);
21080bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21090bdf917eSStefano Zampini         }
21100bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2111142dfd88SStefano Zampini       }
21124fad6a16SStefano Zampini     } else {
21134fad6a16SStefano Zampini       if (dbg_flag) {
2114a929c220SStefano 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);
21154fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21164fad6a16SStefano Zampini       }
21174fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
21184fad6a16SStefano Zampini     }
21194fad6a16SStefano Zampini   }
21207cbb387bSStefano Zampini #else
21217cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
21227cbb387bSStefano Zampini #endif
2123beed3852SStefano Zampini 
21240c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
21250c7d97c5SJed Brown 
2126da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
21270c7d97c5SJed Brown     {
21287cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
21290c7d97c5SJed Brown       /* we need additional variables */
21300c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
21310c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
21320c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
21330c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
21340c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
21350c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
21360c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
21370c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
21380c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
21390c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
21400c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
21410c7d97c5SJed Brown       MetisInt    *faces_adjncy;
21420c7d97c5SJed Brown       MetisInt    *faces_xadj;
21430c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
21440c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
21450c7d97c5SJed Brown       PetscInt    *array_int;
21460c7d97c5SJed Brown       PetscMPIInt my_faces=0;
21470c7d97c5SJed Brown       PetscMPIInt total_faces=0;
21483828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
21490c7d97c5SJed Brown 
21500c7d97c5SJed Brown       /* define some quantities */
21510c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
21520c7d97c5SJed Brown       coarse_mat_type = MATIS;
21530c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
2154142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
21550c7d97c5SJed Brown 
21560c7d97c5SJed Brown       /* details of coarse decomposition */
2157a929c220SStefano Zampini       n_subdomains = active_procs;
21580c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2159a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
21603828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
21613828260eSStefano Zampini 
2162a929c220SStefano Zampini #if 0
2163a929c220SStefano Zampini       PetscMPIInt *old_ranks;
2164a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2165a929c220SStefano Zampini       MatPartitioning mat_part;
2166a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2167a929c220SStefano Zampini       PetscViewer viewer_test;
2168a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
2169a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
2170a929c220SStefano Zampini       Mat         mat_adj;
2171a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2172a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2173a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2174a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2175a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2176a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2177a929c220SStefano Zampini       if (im_active) {
2178a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2179a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2180a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2181a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2182a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2183674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2184674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2185a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2186a929c220SStefano Zampini         k = pcis->n_neigh-1;
2187a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2188a929c220SStefano Zampini         ii[0]=0;
2189a929c220SStefano Zampini         ii[1]=k;
2190a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2191674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2192a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
21930298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2194a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2195a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2196a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2197a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2198a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2199a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2200a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2201a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2202a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2203a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2204a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2205a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2206a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2207a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2208a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2209a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2210a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2211a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2212a929c220SStefano Zampini       }
2213a929c220SStefano Zampini #endif
2214a929c220SStefano Zampini 
22154fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
22160c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
22173828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
22180c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
22190c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22200c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
22210c7d97c5SJed Brown         }
22220c7d97c5SJed Brown       }
22230c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
22240c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22257cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
22260c7d97c5SJed Brown             my_faces++;
22270c7d97c5SJed Brown             break;
22280c7d97c5SJed Brown           }
22290c7d97c5SJed Brown         }
22300c7d97c5SJed Brown       }
22310c7d97c5SJed Brown 
223253cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
22330c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
22340c7d97c5SJed Brown       my_faces=0;
22350c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
22360c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
22377cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
22380c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
22390c7d97c5SJed Brown             my_faces++;
22400c7d97c5SJed Brown             break;
22410c7d97c5SJed Brown           }
22420c7d97c5SJed Brown         }
22430c7d97c5SJed Brown       }
22440c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22450c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
22460c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
22470c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
22480c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
22490c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
22500c7d97c5SJed Brown       }
225153cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
22520c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22530c7d97c5SJed Brown         faces_xadj[0]=0;
22540c7d97c5SJed Brown         faces_displacements[0]=0;
22550c7d97c5SJed Brown         j=0;
22560c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
22570c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
22580c7d97c5SJed Brown           if (number_of_faces[i-1]) {
22590c7d97c5SJed Brown             j++;
22600c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
22610c7d97c5SJed Brown           }
22620c7d97c5SJed Brown         }
22630c7d97c5SJed Brown       }
226453cdbc3dSStefano 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);
22650c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
22660c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
22670c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
22683828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
22690c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
22700c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
22710c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
22720c7d97c5SJed Brown       }
22730c7d97c5SJed Brown 
22740c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
2275674ae819SStefano Zampini 
22763828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
2277674ae819SStefano Zampini 
22780c7d97c5SJed Brown         ncon=1;
22790c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
22800c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
22810c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
22820c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
22830c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
22840c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
22850c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
22864fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
22873828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
22883828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
22893828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
22900c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2291674ae819SStefano 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);
22923828260eSStefano Zampini           } else {
22933828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2294674ae819SStefano 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);
22953828260eSStefano Zampini           }
22964fad6a16SStefano Zampini         } else {
22972fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
22984fad6a16SStefano Zampini         }
22990c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
23000c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
23010bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
23022fa5cd67SKarl Rupp 
23030c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
23042fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
23052fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
23060c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
23070c7d97c5SJed Brown       }
23080c7d97c5SJed Brown 
23090c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
23100c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2311da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2312da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
23130c7d97c5SJed Brown       }
2314da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2315da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
231653cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
23170c7d97c5SJed Brown 
23180c7d97c5SJed Brown       if ( coarse_color == 0 ) {
231953cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
232053cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
23210c7d97c5SJed Brown       } else {
23220c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
23230c7d97c5SJed Brown       }
23240c7d97c5SJed Brown 
23257cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
23260c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
23270c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
23280bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
23290bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
23300c7d97c5SJed Brown         /* some initializations */
23310c7d97c5SJed Brown         displacements_recv[0]=0;
23320bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
23330c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
23340bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
23350bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
23362fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
23370bdf917eSStefano Zampini           }
23380bdf917eSStefano Zampini         }
23390c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
23402fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
23412fa5cd67SKarl Rupp 
23420c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
23430c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
23440c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
23453828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
23460c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
23470c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
23483828260eSStefano Zampini               total_count_recv[j]+=1;
23490c7d97c5SJed Brown             }
23500c7d97c5SJed Brown           }
23510c7d97c5SJed Brown         }
2352da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
23533828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
23543828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
23553828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
23563828260eSStefano Zampini           }
23573828260eSStefano Zampini           printf("\n");
2358da1bb401SStefano Zampini         }*/
23590c7d97c5SJed Brown 
23600c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
23610bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
23620bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
23630bdf917eSStefano Zampini         }
2364da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2365674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
23663828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
23673828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
23683828260eSStefano Zampini           } else {
23693828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
23703828260eSStefano Zampini           }
2371da1bb401SStefano Zampini         printf("\n");*/
23720c7d97c5SJed Brown       }
23730c7d97c5SJed Brown 
23740c7d97c5SJed Brown       /* Scatter new decomposition for send details */
237553cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
23760c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
23770c7d97c5SJed Brown       if ( coarse_color == 0) {
237853cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
23790c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
238053cdbc3dSStefano 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);
23810c7d97c5SJed Brown       }
23820c7d97c5SJed Brown 
2383da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2384da1bb401SStefano Zampini       if (coarse_color == 0) {
2385da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2386da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
2387da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2388da1bb401SStefano Zampini         printf("\n");
2389da1bb401SStefano Zampini       }*/
23900c7d97c5SJed Brown 
23910c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
23920bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2393da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
23940bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
23950c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
23960c7d97c5SJed Brown       }
23977cbb387bSStefano Zampini #endif
23980c7d97c5SJed Brown       break;
23990c7d97c5SJed Brown     }
24000c7d97c5SJed Brown 
24010c7d97c5SJed Brown     case(REPLICATED_BDDC):
24020c7d97c5SJed Brown 
24030c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
24040c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
24050c7d97c5SJed Brown       coarse_pc_type  = PCLU;
240653cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24070c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
24080c7d97c5SJed Brown       active_rank = rank_prec_comm;
24090c7d97c5SJed Brown       break;
24100c7d97c5SJed Brown 
24110c7d97c5SJed Brown     case(PARALLEL_BDDC):
24120c7d97c5SJed Brown 
24130c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2414674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
24150c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
241653cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24170c7d97c5SJed Brown       coarse_comm = prec_comm;
24180c7d97c5SJed Brown       active_rank = rank_prec_comm;
24190c7d97c5SJed Brown       break;
24200c7d97c5SJed Brown 
24210c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
24220c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
2423674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
24240c7d97c5SJed Brown       coarse_pc_type = PCLU;
242553cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
24260c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
24270c7d97c5SJed Brown       active_rank = master_proc;
24280c7d97c5SJed Brown       break;
24290c7d97c5SJed Brown   }
24300c7d97c5SJed Brown 
24310c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
24320c7d97c5SJed Brown 
24330c7d97c5SJed Brown     case(SCATTERS_BDDC):
24340c7d97c5SJed Brown       {
24350c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
24360c7d97c5SJed Brown 
24372e8d2280SStefano Zampini           IS coarse_IS;
24382e8d2280SStefano Zampini 
2439523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2440523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2441523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
2442523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2443523858cfSStefano Zampini             /* nonzeros */
2444523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2445523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2446523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2447523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
2448523858cfSStefano Zampini             }
2449523858cfSStefano Zampini           } else {
24500c7d97c5SJed Brown             PetscMPIInt send_size;
2451ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
24520c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
24530c7d97c5SJed Brown             PetscInt    ii,jj;
24540c7d97c5SJed Brown             MPI_Request *requests;
2455ef028eecSStefano Zampini 
2456523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2457523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
2458523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
2459523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2460523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
2461523858cfSStefano Zampini             j = 0;
2462523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2463523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
2464523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
2465523858cfSStefano Zampini             }
2466523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
2467523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
24680c7d97c5SJed Brown             /* allocate auxiliary space */
2469523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
24700c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
24710c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
24720c7d97c5SJed Brown             /* allocate stuffs for message massing */
24730c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2474523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2475523858cfSStefano Zampini             /* send indices to be inserted */
2476523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2477523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
2478523858cfSStefano 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);
2479523858cfSStefano Zampini             }
2480523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2481523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
2482ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2483ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
2484ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
2485ef028eecSStefano Zampini               }
2486ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2487523858cfSStefano Zampini             }
2488523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2489ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2490ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2491ef028eecSStefano Zampini             }
24920c7d97c5SJed Brown             j = 0;
24930c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
24942e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
24952e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
24960c7d97c5SJed Brown               localdispl2[i] = j;
24970c7d97c5SJed Brown               j += localsizes2[i];
2498523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
24994fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
25002e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
25014fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
25020c7d97c5SJed Brown               }
25034fad6a16SStefano Zampini             }
2504523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
25050c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
25060c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
25070c7d97c5SJed Brown             ins_local_primal_size = 0;
2508ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
2509ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
25100c7d97c5SJed Brown                 ins_local_primal_size++;
2511ea7e1babSStefano Zampini               }
2512ea7e1babSStefano Zampini             }
25130c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
25140c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
25150c7d97c5SJed Brown             j = 0;
2516ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
2517ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
25182e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
25192e8d2280SStefano Zampini                 j++;
2520ea7e1babSStefano Zampini               }
2521ea7e1babSStefano Zampini             }
2522523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2523523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2524523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2525523858cfSStefano Zampini             }
2526523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2527523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2528523858cfSStefano 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);
2529523858cfSStefano Zampini             }
2530523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2531523858cfSStefano Zampini             /* nonzeros */
2532523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2533523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
25340c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
25350c7d97c5SJed Brown             j=0;
25360c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
25370c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
25380c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
25390c7d97c5SJed Brown               } else {
25400c7d97c5SJed Brown                 aux_ins_indices[i]=j;
25410c7d97c5SJed Brown                 j++;
25420c7d97c5SJed Brown               }
25430c7d97c5SJed Brown             }
25444fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
2545523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
2546523858cfSStefano Zampini               for (k=0;k<j;k++) {
2547523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
25480c7d97c5SJed Brown               }
25490c7d97c5SJed Brown             }
2550523858cfSStefano Zampini             /* check */
2551523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2552523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2553523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
25540c7d97c5SJed Brown               }
25550c7d97c5SJed Brown             }
25560c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
25570c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
25580c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
25594fad6a16SStefano Zampini           }
25600c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
2561142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
25620c7d97c5SJed Brown           coarse_comm = prec_comm;
25630c7d97c5SJed Brown           active_rank = rank_prec_comm;
25640c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
25650c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
25660c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
25672e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
25680c7d97c5SJed Brown           /* arrays for values insertion */
25690c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
25702e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
25710c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
25720c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
25730c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
25744fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
25754fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
25764fad6a16SStefano Zampini             }
25770c7d97c5SJed Brown           }
25780c7d97c5SJed Brown         }
25790c7d97c5SJed Brown         break;
2580674ae819SStefano Zampini 
25810c7d97c5SJed Brown     }
25820c7d97c5SJed Brown 
25830c7d97c5SJed Brown     case(GATHERS_BDDC):
25840c7d97c5SJed Brown       {
2585674ae819SStefano Zampini 
25860c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
2587ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
25880c7d97c5SJed Brown 
25890c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
25900c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
25910bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
25920c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
25930c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
25940c7d97c5SJed Brown           /* arrays for values insertion */
25952fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
25960c7d97c5SJed Brown           localdispl2[0]=0;
25972fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
25980c7d97c5SJed Brown           j=0;
25992fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
26000c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
26010c7d97c5SJed Brown         }
26020c7d97c5SJed Brown 
26030c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
26040c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2605ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
26062fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
26072fa5cd67SKarl Rupp 
26080c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2609ef028eecSStefano 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);
261053cdbc3dSStefano 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);
26110c7d97c5SJed Brown         } else {
2612ef028eecSStefano 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);
261353cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
26140c7d97c5SJed Brown         }
2615ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
26160c7d97c5SJed Brown         break;
2617da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
26180c7d97c5SJed Brown   }
26190c7d97c5SJed Brown 
26200c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
26210c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2622142dfd88SStefano Zampini 
2623142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2624142dfd88SStefano Zampini 
26250c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
26260c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
26270c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
26280c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2629674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2630674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
26313b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2632da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
26333b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
26340c7d97c5SJed Brown     } else {
26354fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
26363b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
26370c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2638674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2639674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
26403b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2641da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2642a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
26430c7d97c5SJed Brown     }
2644142dfd88SStefano Zampini     /* preallocation */
2645142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2646ef028eecSStefano Zampini 
2647674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2648ef028eecSStefano Zampini 
2649142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2650142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2651674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2652ef028eecSStefano Zampini 
2653142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2654ef028eecSStefano Zampini 
2655ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2656ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2657ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2658ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2659ef028eecSStefano Zampini 
2660ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2661674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2662ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2663ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2664ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2665ef028eecSStefano Zampini 
2666ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2667ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2668ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2669ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2670ef028eecSStefano Zampini 
2671ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2672ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2673142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2674ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2675ef028eecSStefano Zampini             row_ownership[j]=i;
2676142dfd88SStefano Zampini           }
2677142dfd88SStefano Zampini         }
2678ef028eecSStefano Zampini 
2679ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2680ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2681ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2682ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2683ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2684ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2685ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2686ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2687142dfd88SStefano Zampini             } else {
2688ef028eecSStefano Zampini               my_onz[i] += 1.0;
2689142dfd88SStefano Zampini             }
2690ef028eecSStefano Zampini             if (i != j) {
2691ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2692ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2693ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2694142dfd88SStefano Zampini               } else {
2695ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2696142dfd88SStefano Zampini               }
2697142dfd88SStefano Zampini             }
2698142dfd88SStefano Zampini           }
2699142dfd88SStefano Zampini         }
2700ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2701ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2702a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2703ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2704ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2705a929c220SStefano Zampini         }
2706ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2707ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2708ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2709ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2710ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2711ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
27125b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
27132fa5cd67SKarl Rupp 
2714ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2715ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
27165b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
27172fa5cd67SKarl Rupp 
2718ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2719ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2720ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2721ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2722ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2723ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2724142dfd88SStefano Zampini       } else {
2725142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2726142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2727142dfd88SStefano Zampini           offset2=localdispl2[k];
2728142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2729ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2730ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2731ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2732ef028eecSStefano Zampini           }
2733142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2734142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2735142dfd88SStefano Zampini           }
2736ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2737142dfd88SStefano Zampini         }
2738142dfd88SStefano Zampini       }
27392fa5cd67SKarl Rupp 
2740142dfd88SStefano Zampini       /* check */
2741142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
27422fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
27432fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2744142dfd88SStefano Zampini       }
2745d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2746d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2747142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2748142dfd88SStefano Zampini     } else {
2749523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2750523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2751142dfd88SStefano Zampini     }
2752142dfd88SStefano Zampini     /* insert values */
2753523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
27540c7d97c5SJed 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);
2755523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2756523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2757523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2758523858cfSStefano 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);
2759523858cfSStefano Zampini       } else {
2760523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2761523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2762523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2763523858cfSStefano Zampini           offset2 = localdispl2[k];
2764523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2765ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2766ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2767ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2768ef028eecSStefano Zampini           }
2769523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2770523858cfSStefano 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);
2771ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2772523858cfSStefano Zampini         }
2773523858cfSStefano Zampini       }
2774523858cfSStefano Zampini       ins_local_primal_indices = 0;
2775523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2776ea7e1babSStefano Zampini     } else {
2777ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2778ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2779ea7e1babSStefano Zampini         offset2=localdispl2[k];
2780ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2781ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2782ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2783ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2784ef028eecSStefano Zampini         }
2785ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2786ea7e1babSStefano 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);
2787ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2788ea7e1babSStefano Zampini       }
2789ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2790ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2791ea7e1babSStefano Zampini     }
27920c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27930c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2794142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2795142dfd88SStefano Zampini     if (issym) {
2796142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2797142dfd88SStefano Zampini     }
27980c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
27990bdf917eSStefano Zampini   }
28000bdf917eSStefano Zampini 
28010bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
28020bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
28030bdf917eSStefano Zampini      IS local_IS,global_IS;
28040bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
28050bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
28060bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
28070bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
28080bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
28090bdf917eSStefano Zampini   }
28100bdf917eSStefano Zampini 
2811a929c220SStefano Zampini   /* free memory no longer needed */
2812a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2813a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2814a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2815a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2816a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2817a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2818a929c220SStefano Zampini 
2819674ae819SStefano Zampini   /* Compute coarse null space */
2820674ae819SStefano Zampini   CoarseNullSpace = 0;
28210bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2822674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
28230bdf917eSStefano Zampini   }
28240bdf917eSStefano Zampini 
28250bdf917eSStefano Zampini   /* KSP for coarse problem */
28260bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
28272e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
28280bdf917eSStefano Zampini 
282953cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
283053cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
283153cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
28323b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
283353cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
283453cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
283553cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
28360c7d97c5SJed Brown     /* Allow user's customization */
2837da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
28380c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
283953cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
28404fad6a16SStefano Zampini       i = pcbddc->current_level+1;
28414fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
28424fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
28434fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
284453cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2845674ae819SStefano Zampini       if (CoarseNullSpace) {
2846674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2847674ae819SStefano Zampini       }
28484fad6a16SStefano Zampini       if (dbg_flag) {
28494fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
28504fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
285153cdbc3dSStefano Zampini       }
2852674ae819SStefano Zampini     } else {
2853674ae819SStefano Zampini       if (CoarseNullSpace) {
2854674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2855674ae819SStefano Zampini       }
28564fad6a16SStefano Zampini     }
28574fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
285853cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2859142dfd88SStefano Zampini 
28600298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
28612e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
28622e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
28632e8d2280SStefano Zampini     if (j == 1) {
28642e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
28652e8d2280SStefano Zampini       if (isbddc) {
28662e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
28675619798eSStefano Zampini       }
28685619798eSStefano Zampini     }
28690c7d97c5SJed Brown   }
2870a929c220SStefano Zampini   /* Check coarse problem if requested */
2871142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2872142dfd88SStefano Zampini     KSP check_ksp;
2873142dfd88SStefano Zampini     PC  check_pc;
2874142dfd88SStefano Zampini     Vec check_vec;
2875142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
287619fd82e9SBarry Smith     KSPType check_ksp_type;
28770c7d97c5SJed Brown 
2878142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2879142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2880142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
28810bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2882142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
28832fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
28842fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2885142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2886142dfd88SStefano Zampini     } else {
2887142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2888142dfd88SStefano Zampini     }
2889142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2890142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2891142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2892142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2893142dfd88SStefano Zampini     /* create random vec */
2894142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
28950298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2896674ae819SStefano Zampini     if (CoarseNullSpace) {
28971cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
2898674ae819SStefano Zampini     }
2899142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2900142dfd88SStefano Zampini     /* solve coarse problem */
2901142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2902674ae819SStefano Zampini     if (CoarseNullSpace) {
29031cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
2904674ae819SStefano Zampini     }
2905142dfd88SStefano Zampini     /* check coarse problem residual error */
2906142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2907142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2908142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2909142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2910142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2911142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2912142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2913142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2914142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2915142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2916e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
29173b03a366Sstefano_zampini     }
2918142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2919142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2920142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
292153cdbc3dSStefano Zampini   }
2922674ae819SStefano Zampini   if (dbg_flag) {
2923da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2924da1bb401SStefano Zampini   }
2925674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2926a0ba757dSStefano Zampini 
29270c7d97c5SJed Brown   PetscFunctionReturn(0);
29280c7d97c5SJed Brown }
29290c7d97c5SJed Brown 
2930