xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 62a6ff1d89f223ad7991b4be5dee3de016785c7b)
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);
454fb223d50SStefano Zampini   /* TODO: PCBDDCGraphSetAdjacency */
455674ae819SStefano Zampini   /* get CSR into graph structure */
456da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
457674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
459674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
460674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
461da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4621a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4631a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
464674ae819SStefano Zampini   }
465575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46636e030ebSStefano Zampini   PetscFunctionReturn(0);
46736e030ebSStefano Zampini }
4681e6b0712SBarry Smith 
46936e030ebSStefano Zampini #undef __FUNCT__
470da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
47136e030ebSStefano Zampini /*@
472da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47336e030ebSStefano Zampini 
47436e030ebSStefano Zampini    Not collective
47536e030ebSStefano Zampini 
47636e030ebSStefano Zampini    Input Parameters:
47736e030ebSStefano Zampini +  pc - the preconditioning context
478da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
479da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
480da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
481da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48236e030ebSStefano Zampini 
48336e030ebSStefano Zampini    Level: intermediate
48436e030ebSStefano Zampini 
48536e030ebSStefano Zampini    Notes:
48636e030ebSStefano Zampini 
48736e030ebSStefano Zampini .seealso: PCBDDC
48836e030ebSStefano Zampini @*/
4891a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
49036e030ebSStefano Zampini {
491575ad6abSStefano Zampini   void (*f)(void) = 0;
49236e030ebSStefano Zampini   PetscErrorCode ierr;
49336e030ebSStefano Zampini 
49436e030ebSStefano Zampini   PetscFunctionBegin;
49536e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
496674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
497674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
498674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
499674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
500da1bb401SStefano Zampini   }
50136e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
502575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
503575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
504575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
505575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
506575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50736e030ebSStefano Zampini   }
50836e030ebSStefano Zampini   PetscFunctionReturn(0);
50936e030ebSStefano Zampini }
5109c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5111e6b0712SBarry Smith 
5129c0446d6SStefano Zampini #undef __FUNCT__
5139c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5149c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5159c0446d6SStefano Zampini {
5169c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5179c0446d6SStefano Zampini   PetscInt i;
5189c0446d6SStefano Zampini   PetscErrorCode ierr;
5199c0446d6SStefano Zampini 
5209c0446d6SStefano Zampini   PetscFunctionBegin;
521da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5229c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5239c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5249c0446d6SStefano Zampini   }
525d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
526da1bb401SStefano Zampini   /* allocate space then set */
5279c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5289c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
529da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
530da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5319c0446d6SStefano Zampini   }
5329c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5339c0446d6SStefano Zampini   PetscFunctionReturn(0);
5349c0446d6SStefano Zampini }
5351e6b0712SBarry Smith 
5369c0446d6SStefano Zampini #undef __FUNCT__
5379c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5389c0446d6SStefano Zampini /*@
539da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5409c0446d6SStefano Zampini 
5419c0446d6SStefano Zampini    Not collective
5429c0446d6SStefano Zampini 
5439c0446d6SStefano Zampini    Input Parameters:
5449c0446d6SStefano Zampini +  pc - the preconditioning context
545da1bb401SStefano Zampini -  n - number of index sets defining the fields
546da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5479c0446d6SStefano Zampini 
5489c0446d6SStefano Zampini    Level: intermediate
5499c0446d6SStefano Zampini 
5509c0446d6SStefano Zampini    Notes:
5519c0446d6SStefano Zampini 
5529c0446d6SStefano Zampini .seealso: PCBDDC
5539c0446d6SStefano Zampini @*/
5549c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5559c0446d6SStefano Zampini {
5569c0446d6SStefano Zampini   PetscErrorCode ierr;
5579c0446d6SStefano Zampini 
5589c0446d6SStefano Zampini   PetscFunctionBegin;
5599c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5609c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5619c0446d6SStefano Zampini   PetscFunctionReturn(0);
5629c0446d6SStefano Zampini }
563da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
564534831adSStefano Zampini #undef __FUNCT__
565534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
566534831adSStefano Zampini /* -------------------------------------------------------------------------- */
567534831adSStefano Zampini /*
568534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
569534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5709c0446d6SStefano Zampini 
571534831adSStefano Zampini    Input Parameter:
572534831adSStefano Zampini +  pc - the preconditioner contex
573534831adSStefano Zampini 
574534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
575534831adSStefano Zampini 
576534831adSStefano Zampini    Notes:
577534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
578534831adSStefano Zampini    the user, but instead is called by KSPSolve().
579534831adSStefano Zampini */
580534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
581534831adSStefano Zampini {
582534831adSStefano Zampini   PetscErrorCode ierr;
583534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
584534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
585534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
586534831adSStefano Zampini   Mat            temp_mat;
5873972b0daSStefano Zampini   IS             dirIS;
5883972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5893972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5903972b0daSStefano Zampini   Vec            used_vec;
5913972b0daSStefano Zampini   PetscBool      guess_nonzero;
592534831adSStefano Zampini 
593534831adSStefano Zampini   PetscFunctionBegin;
594*62a6ff1dSStefano Zampini   /* Creates parallel work vectors used in presolve. */
595*62a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
596*62a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
597*62a6ff1dSStefano Zampini   }
598*62a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
599*62a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
600*62a6ff1dSStefano Zampini   }
6013972b0daSStefano Zampini   if (x) {
6023972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
6033972b0daSStefano Zampini     used_vec = x;
6043972b0daSStefano Zampini   } else {
6053972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
6063972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
6073972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6083972b0daSStefano Zampini   }
6093972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6103972b0daSStefano Zampini   if (ksp) {
6113972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6123972b0daSStefano Zampini     if ( !guess_nonzero ) {
6133972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6143972b0daSStefano Zampini     }
6153972b0daSStefano Zampini   }
6163308cffdSStefano Zampini 
617*62a6ff1dSStefano Zampini   if (rhs) { /* TODO: wiser handling of rhs removal, which is only needed in case of zeroed rows */
6183972b0daSStefano Zampini     /* store the original rhs */
6193972b0daSStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6203972b0daSStefano Zampini 
6213972b0daSStefano Zampini     /* Take into account zeroed rows -> change rhs and store solution removed */
6223972b0daSStefano Zampini     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6233972b0daSStefano Zampini     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6243972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6253972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6263972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6273972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6283972b0daSStefano Zampini     ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6293972b0daSStefano Zampini     if (dirIS) {
6303972b0daSStefano Zampini       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6313972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6323972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6333972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6342fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6353972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6363972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6373972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6383972b0daSStefano Zampini     }
6393972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6403972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
641b76ba322SStefano Zampini 
6423972b0daSStefano Zampini     /* remove the computed solution from the rhs */
6433972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6443972b0daSStefano Zampini     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6453972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6463308cffdSStefano Zampini   }
647b76ba322SStefano Zampini 
648b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6493972b0daSStefano Zampini   if (x) {
6503972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6513972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
65215aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
653b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
654b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
655b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
656b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
657b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
658b76ba322SStefano Zampini       if (ksp) {
659b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
660b76ba322SStefano Zampini       }
661b76ba322SStefano Zampini     }
6623972b0daSStefano Zampini   }
663b76ba322SStefano Zampini 
664674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
665b76ba322SStefano Zampini     /* swap pointers for local matrices */
666b76ba322SStefano Zampini     temp_mat = matis->A;
667b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
668b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
6693308cffdSStefano Zampini   }
6703308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && rhs) {
671b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
672b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
673b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
674b76ba322SStefano Zampini     /* from original basis to modified basis */
675b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
676b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
677b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
678b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
679674ae819SStefano Zampini   }
6800bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
681d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
682d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
683b76ba322SStefano Zampini   }
6840bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
685534831adSStefano Zampini   PetscFunctionReturn(0);
686534831adSStefano Zampini }
687534831adSStefano Zampini /* -------------------------------------------------------------------------- */
688534831adSStefano Zampini #undef __FUNCT__
689534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
690534831adSStefano Zampini /* -------------------------------------------------------------------------- */
691534831adSStefano Zampini /*
692534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
693534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
694534831adSStefano Zampini 
695534831adSStefano Zampini    Input Parameter:
696534831adSStefano Zampini +  pc - the preconditioner contex
697534831adSStefano Zampini 
698534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
699534831adSStefano Zampini 
700534831adSStefano Zampini    Notes:
701534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
702534831adSStefano Zampini    the user, but instead is called by KSPSolve().
703534831adSStefano Zampini */
704534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
705534831adSStefano Zampini {
706534831adSStefano Zampini   PetscErrorCode ierr;
707534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
708534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
709534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
710534831adSStefano Zampini   Mat            temp_mat;
711534831adSStefano Zampini 
712534831adSStefano Zampini   PetscFunctionBegin;
713674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
714534831adSStefano Zampini     /* swap pointers for local matrices */
715534831adSStefano Zampini     temp_mat = matis->A;
716534831adSStefano Zampini     matis->A = pcbddc->local_mat;
717534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
7183425bc38SStefano Zampini   }
7193308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && x) {
720534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
721534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
722534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
723534831adSStefano Zampini     /* from modified basis to original basis */
724534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
725534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
726534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
727534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
728534831adSStefano Zampini   }
7293972b0daSStefano Zampini   /* add solution removed in presolve */
7303425bc38SStefano Zampini   if (x) {
7313425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7323425bc38SStefano Zampini   }
733fb223d50SStefano Zampini   /* restore rhs to its original state */
734fb223d50SStefano Zampini   if (rhs) {
735fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
736fb223d50SStefano Zampini   }
737534831adSStefano Zampini   PetscFunctionReturn(0);
738534831adSStefano Zampini }
739534831adSStefano Zampini /* -------------------------------------------------------------------------- */
74053cdbc3dSStefano Zampini #undef __FUNCT__
74153cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7420c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7430c7d97c5SJed Brown /*
7440c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7450c7d97c5SJed Brown                   by setting data structures and options.
7460c7d97c5SJed Brown 
7470c7d97c5SJed Brown    Input Parameter:
74853cdbc3dSStefano Zampini +  pc - the preconditioner context
7490c7d97c5SJed Brown 
7500c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7510c7d97c5SJed Brown 
7520c7d97c5SJed Brown    Notes:
7530c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7540c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7550c7d97c5SJed Brown */
75653cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7570c7d97c5SJed Brown {
7580c7d97c5SJed Brown   PetscErrorCode ierr;
7590c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
760674ae819SStefano Zampini   MatStructure   flag;
761674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7620c7d97c5SJed Brown 
7630c7d97c5SJed Brown   PetscFunctionBegin;
764674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7653b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7669c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7670c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7680c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7690c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7703b03a366Sstefano_zampini   /* Get stdout for dbg */
771674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
772ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
773e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
774e269702eSStefano Zampini   }
775674ae819SStefano Zampini   /* first attempt to split work */
776674ae819SStefano Zampini   if (pc->setupcalled) {
777674ae819SStefano Zampini     computeis = PETSC_FALSE;
778674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
779674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
780674ae819SStefano Zampini       computetopography = PETSC_FALSE;
781674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
782674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
783674ae819SStefano Zampini       computetopography = PETSC_FALSE;
784674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
785674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
786674ae819SStefano Zampini       computetopography = PETSC_TRUE;
787674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
788674ae819SStefano Zampini     }
789674ae819SStefano Zampini   } else {
790674ae819SStefano Zampini     computeis = PETSC_TRUE;
791674ae819SStefano Zampini     computetopography = PETSC_TRUE;
792674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
793674ae819SStefano Zampini   }
794674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
795674ae819SStefano Zampini   if (computeis) {
796674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
797674ae819SStefano Zampini   }
798674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
799674ae819SStefano Zampini   if (computetopography) {
800674ae819SStefano Zampini     /* reset data */
801674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
802674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
803674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
804674ae819SStefano Zampini   }
805674ae819SStefano Zampini   if (computesolvers) {
806674ae819SStefano Zampini     /* reset data */
807674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
808674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
8090c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
8100c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
811674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
8120c7d97c5SJed Brown   }
8130c7d97c5SJed Brown   PetscFunctionReturn(0);
8140c7d97c5SJed Brown }
8150c7d97c5SJed Brown 
8160c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8170c7d97c5SJed Brown /*
8180c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8190c7d97c5SJed Brown 
8200c7d97c5SJed Brown    Input Parameters:
8210c7d97c5SJed Brown .  pc - the preconditioner context
8220c7d97c5SJed Brown .  r - input vector (global)
8230c7d97c5SJed Brown 
8240c7d97c5SJed Brown    Output Parameter:
8250c7d97c5SJed Brown .  z - output vector (global)
8260c7d97c5SJed Brown 
8270c7d97c5SJed Brown    Application Interface Routine: PCApply()
8280c7d97c5SJed Brown  */
8290c7d97c5SJed Brown #undef __FUNCT__
8300c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
83153cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8320c7d97c5SJed Brown {
8330c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8340c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8350c7d97c5SJed Brown   PetscErrorCode    ierr;
8363b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8373b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8382617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8390c7d97c5SJed Brown 
8400c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8410c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
84229622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8430c7d97c5SJed Brown 
8440c7d97c5SJed Brown   PetscFunctionBegin;
84515aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8460c7d97c5SJed Brown     /* First Dirichlet solve */
8470c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8480c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
84953cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8500c7d97c5SJed Brown     /*
8510c7d97c5SJed Brown       Assembling right hand side for BDDC operator
852674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
853674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8540c7d97c5SJed Brown     */
8550c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8560c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
85729622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8580c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8590c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8600c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8610c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
862674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
863b76ba322SStefano Zampini   } else {
8640bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
865b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
866674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
867b76ba322SStefano Zampini   }
868b76ba322SStefano Zampini 
8692617d88aSStefano Zampini   /* Apply interface preconditioner
8702617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8712617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8722617d88aSStefano Zampini 
873674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
874674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8750c7d97c5SJed Brown 
8763b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8770c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8780c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8790c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
88029622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
88153cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8820c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
88329622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8840c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8850c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8860c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8870c7d97c5SJed Brown   PetscFunctionReturn(0);
8880c7d97c5SJed Brown }
889da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
890674ae819SStefano Zampini 
891da1bb401SStefano Zampini #undef __FUNCT__
892da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
893da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
894da1bb401SStefano Zampini {
895da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
896da1bb401SStefano Zampini   PetscErrorCode ierr;
897da1bb401SStefano Zampini 
898da1bb401SStefano Zampini   PetscFunctionBegin;
899da1bb401SStefano Zampini   /* free data created by PCIS */
900da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
901674ae819SStefano Zampini   /* free BDDC custom data  */
902674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
903674ae819SStefano Zampini   /* destroy objects related to topography */
904674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
905674ae819SStefano Zampini   /* free allocated graph structure */
906da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
907674ae819SStefano Zampini   /* free data for scaling operator */
908674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
909674ae819SStefano Zampini   /* free solvers stuff */
910674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
91133bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
91233bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
913ac78edfcSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
914*62a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
915*62a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
916*62a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
9173425bc38SStefano Zampini   /* remove functions */
918674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
919bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
920bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
921bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
922bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
923bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
924bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
925bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
926bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
927bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
928bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
929bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
930bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
931bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
932674ae819SStefano Zampini   /* Free the private data structure */
933674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
934da1bb401SStefano Zampini   PetscFunctionReturn(0);
935da1bb401SStefano Zampini }
9363425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9371e6b0712SBarry Smith 
9383425bc38SStefano Zampini #undef __FUNCT__
9393425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9403425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9413425bc38SStefano Zampini {
942674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9433425bc38SStefano Zampini   PC_IS*         pcis;
9443425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9453425bc38SStefano Zampini   PetscErrorCode ierr;
9460c7d97c5SJed Brown 
9473425bc38SStefano Zampini   PetscFunctionBegin;
9483425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9493425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9503425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9513425bc38SStefano Zampini 
9523425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9533425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
9543308cffdSStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
9553425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9563425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9573425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
958fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
959fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
9603425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9613425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
962674ae819SStefano Zampini   /* Apply partition of unity */
9633425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
964674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
96529622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9663425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9673425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9683425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9693425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9703425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9713425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9723425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
973674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9743425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9753425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9763425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9773425bc38SStefano Zampini   }
9783425bc38SStefano Zampini   /* BDDC rhs */
9793425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
98029622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9813425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9823425bc38SStefano Zampini   }
9833425bc38SStefano Zampini   /* apply BDDC */
9843425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9853425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9863425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9873425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9883425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9893425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9903425bc38SStefano Zampini   /* restore original rhs */
9913425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9923425bc38SStefano Zampini   PetscFunctionReturn(0);
9933425bc38SStefano Zampini }
9941e6b0712SBarry Smith 
9953425bc38SStefano Zampini #undef __FUNCT__
9963425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9973425bc38SStefano Zampini /*@
9983425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9993425bc38SStefano Zampini 
10003425bc38SStefano Zampini    Collective
10013425bc38SStefano Zampini 
10023425bc38SStefano Zampini    Input Parameters:
10033425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10043425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
10053425bc38SStefano Zampini 
10063425bc38SStefano Zampini    Output Parameters:
10073425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
10083425bc38SStefano Zampini 
10093425bc38SStefano Zampini    Level: developer
10103425bc38SStefano Zampini 
10113425bc38SStefano Zampini    Notes:
10123425bc38SStefano Zampini 
10133425bc38SStefano Zampini .seealso: PCBDDC
10143425bc38SStefano Zampini @*/
10153425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
10163425bc38SStefano Zampini {
1017674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10183425bc38SStefano Zampini   PetscErrorCode ierr;
10193425bc38SStefano Zampini 
10203425bc38SStefano Zampini   PetscFunctionBegin;
10213425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10223425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10233425bc38SStefano Zampini   PetscFunctionReturn(0);
10243425bc38SStefano Zampini }
10253425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10261e6b0712SBarry Smith 
10273425bc38SStefano Zampini #undef __FUNCT__
10283425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10293425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10303425bc38SStefano Zampini {
1031674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10323425bc38SStefano Zampini   PC_IS*         pcis;
10333425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10343425bc38SStefano Zampini   PetscErrorCode ierr;
10353425bc38SStefano Zampini 
10363425bc38SStefano Zampini   PetscFunctionBegin;
10373425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10383425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10393425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10403425bc38SStefano Zampini 
10413425bc38SStefano Zampini   /* apply B_delta^T */
10423425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10433425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10443425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10453425bc38SStefano Zampini   /* compute rhs for BDDC application */
10463425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
104729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10483425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10493425bc38SStefano Zampini   }
10503425bc38SStefano Zampini   /* apply BDDC */
10513425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10523425bc38SStefano Zampini   /* put values into standard global vector */
10533425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10543425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
105529622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10563425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10573425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10583425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10593425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10603425bc38SStefano Zampini   }
10613425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10623425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10633425bc38SStefano Zampini   /* final change of basis if needed
10643425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10653308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
10663425bc38SStefano Zampini   PetscFunctionReturn(0);
10673425bc38SStefano Zampini }
10681e6b0712SBarry Smith 
10693425bc38SStefano Zampini #undef __FUNCT__
10703425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10713425bc38SStefano Zampini /*@
10723425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10733425bc38SStefano Zampini 
10743425bc38SStefano Zampini    Collective
10753425bc38SStefano Zampini 
10763425bc38SStefano Zampini    Input Parameters:
10773425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10783425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10793425bc38SStefano Zampini 
10803425bc38SStefano Zampini    Output Parameters:
10813425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10823425bc38SStefano Zampini 
10833425bc38SStefano Zampini    Level: developer
10843425bc38SStefano Zampini 
10853425bc38SStefano Zampini    Notes:
10863425bc38SStefano Zampini 
10873425bc38SStefano Zampini .seealso: PCBDDC
10883425bc38SStefano Zampini @*/
10893425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10903425bc38SStefano Zampini {
1091674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10923425bc38SStefano Zampini   PetscErrorCode ierr;
10933425bc38SStefano Zampini 
10943425bc38SStefano Zampini   PetscFunctionBegin;
10953425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10963425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10973425bc38SStefano Zampini   PetscFunctionReturn(0);
10983425bc38SStefano Zampini }
10993425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
11001e6b0712SBarry Smith 
1101f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1102f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1103f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1104f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1105674ae819SStefano Zampini 
11063425bc38SStefano Zampini #undef __FUNCT__
11073425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
11083425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11093425bc38SStefano Zampini {
1110674ae819SStefano Zampini 
1111674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
11123425bc38SStefano Zampini   Mat            newmat;
1113674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
11143425bc38SStefano Zampini   PC             newpc;
1115ce94432eSBarry Smith   MPI_Comm       comm;
11163425bc38SStefano Zampini   PetscErrorCode ierr;
11173425bc38SStefano Zampini 
11183425bc38SStefano Zampini   PetscFunctionBegin;
1119ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
11203425bc38SStefano Zampini   /* FETIDP linear matrix */
11213425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11223425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11233425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11243425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11253425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11263425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11273425bc38SStefano Zampini   /* FETIDP preconditioner */
11283425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11293425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11303425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11313425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11323425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11333425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11343425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11353425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11363425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11373425bc38SStefano Zampini   /* return pointers for objects created */
11383425bc38SStefano Zampini   *fetidp_mat=newmat;
11393425bc38SStefano Zampini   *fetidp_pc=newpc;
11403425bc38SStefano Zampini   PetscFunctionReturn(0);
11413425bc38SStefano Zampini }
11421e6b0712SBarry Smith 
11433425bc38SStefano Zampini #undef __FUNCT__
11443425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11453425bc38SStefano Zampini /*@
11463425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11473425bc38SStefano Zampini 
11483425bc38SStefano Zampini    Collective
11493425bc38SStefano Zampini 
11503425bc38SStefano Zampini    Input Parameters:
11513425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11523425bc38SStefano Zampini 
11533425bc38SStefano Zampini    Level: developer
11543425bc38SStefano Zampini 
11553425bc38SStefano Zampini    Notes:
11563425bc38SStefano Zampini 
11573425bc38SStefano Zampini .seealso: PCBDDC
11583425bc38SStefano Zampini @*/
11593425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11603425bc38SStefano Zampini {
11613425bc38SStefano Zampini   PetscErrorCode ierr;
11623425bc38SStefano Zampini 
11633425bc38SStefano Zampini   PetscFunctionBegin;
11643425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11653425bc38SStefano Zampini   if (pc->setupcalled) {
11663425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1167f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11683425bc38SStefano Zampini   PetscFunctionReturn(0);
11693425bc38SStefano Zampini }
11700c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1171da1bb401SStefano Zampini /*MC
1172da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11730c7d97c5SJed Brown 
1174da1bb401SStefano Zampini    Options Database Keys:
1175da1bb401SStefano Zampini .    -pcbddc ??? -
1176da1bb401SStefano Zampini 
1177da1bb401SStefano Zampini    Level: intermediate
1178da1bb401SStefano Zampini 
1179da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1180da1bb401SStefano Zampini 
1181da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1182da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1183da1bb401SStefano Zampini           on the subdomains).
1184da1bb401SStefano Zampini 
1185da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1186da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1187da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1188da1bb401SStefano Zampini 
1189da1bb401SStefano Zampini    Contributed by Stefano Zampini
1190da1bb401SStefano Zampini 
1191da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1192da1bb401SStefano Zampini M*/
1193b2573a8aSBarry Smith 
1194da1bb401SStefano Zampini #undef __FUNCT__
1195da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11968cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1197da1bb401SStefano Zampini {
1198da1bb401SStefano Zampini   PetscErrorCode      ierr;
1199da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1200da1bb401SStefano Zampini 
1201da1bb401SStefano Zampini   PetscFunctionBegin;
1202da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1203da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1204da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1205da1bb401SStefano Zampini 
1206da1bb401SStefano Zampini   /* create PCIS data structure */
1207da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1208da1bb401SStefano Zampini 
1209da1bb401SStefano Zampini   /* BDDC specific */
1210674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
12110bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
12123972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1213534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1214534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1215534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1216674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1217674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1218da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1219da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1220da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1221da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1222da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
122315aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
122415aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
1225da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1226da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1227da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1228da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1229da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1230da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1231da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1232da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1233da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1234da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
123529622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1236da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1237da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1238da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1239da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1240da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1241da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1242da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
12439d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1244da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1245b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12464fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12474fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1248674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1249674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1250da1bb401SStefano Zampini 
1251674ae819SStefano Zampini   /* create local graph structure */
1252674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1253674ae819SStefano Zampini 
1254674ae819SStefano Zampini   /* scaling */
1255674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1256674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1257da1bb401SStefano Zampini 
1258da1bb401SStefano Zampini   /* function pointers */
1259da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1260da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1261da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1262da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1263da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1264da1bb401SStefano Zampini   pc->ops->view                = 0;
1265da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1266da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1267da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1268534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1269534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1270da1bb401SStefano Zampini 
1271da1bb401SStefano Zampini   /* composing function */
1272674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1274bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1275bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1276bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1277bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1278bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1279bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1280bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1281bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1284bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1285bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1286da1bb401SStefano Zampini   PetscFunctionReturn(0);
1287da1bb401SStefano Zampini }
12883425bc38SStefano Zampini 
1289da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1290da1bb401SStefano Zampini /* All static functions from now on                                           */
1291da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
129229622bf0SStefano Zampini 
129329622bf0SStefano Zampini #undef __FUNCT__
12944fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
12954fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
12964fad6a16SStefano Zampini {
12974fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
12984fad6a16SStefano Zampini 
12994fad6a16SStefano Zampini   PetscFunctionBegin;
13004fad6a16SStefano Zampini   pcbddc->current_level=level;
13014fad6a16SStefano Zampini   PetscFunctionReturn(0);
13024fad6a16SStefano Zampini }
13033425bc38SStefano Zampini 
13043b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
13050c7d97c5SJed Brown #undef __FUNCT__
13060c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
130753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
13080c7d97c5SJed Brown {
13090c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
13100c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
13110c7d97c5SJed Brown   IS                is_R_local;
1312dcedc2aeSStefano Zampini   PetscErrorCode    ierr;
1313dcedc2aeSStefano Zampini 
1314dcedc2aeSStefano Zampini   PetscFunctionBegin;
1315dcedc2aeSStefano Zampini   /* compute matrix after change of basis and extract local submatrices */
1316dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
1317dcedc2aeSStefano Zampini 
1318dcedc2aeSStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1319dcedc2aeSStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1320dcedc2aeSStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1321dcedc2aeSStefano Zampini   }
1322dcedc2aeSStefano Zampini 
1323dcedc2aeSStefano Zampini   /* Allocate needed vectors */
1324dcedc2aeSStefano Zampini   ierr = PCBDDCCreateWorkVectors(pc);CHKERRQ(ierr);
1325dcedc2aeSStefano Zampini 
1326dcedc2aeSStefano Zampini   /* setup local scatters R_to_B and (optionally) R_to_D : PCBDDCCreateWorkVectors should be called first! */
1327dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc,&is_R_local);CHKERRQ(ierr);
1328dcedc2aeSStefano Zampini 
1329dcedc2aeSStefano Zampini   /* setup local solvers ksp_D and ksp_R */
1330dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,pcis->is_I_local,is_R_local);CHKERRQ(ierr);
1331dcedc2aeSStefano Zampini 
1332dcedc2aeSStefano Zampini   /* Assemble all remaining stuff needed to apply BDDC  */
1333dcedc2aeSStefano Zampini   {
1334dcedc2aeSStefano Zampini     Mat          A_RV,A_VR,A_VV;
1335dcedc2aeSStefano Zampini     Mat          M1;
1336dcedc2aeSStefano Zampini     Mat          C_CR;
1337dcedc2aeSStefano Zampini     Mat          AUXMAT;
1338dcedc2aeSStefano Zampini     Vec          vec1_C;
1339dcedc2aeSStefano Zampini     Vec          vec2_C;
1340dcedc2aeSStefano Zampini     Vec          vec1_V;
1341dcedc2aeSStefano Zampini     Vec          vec2_V;
1342dcedc2aeSStefano Zampini     IS           is_C_local,is_V_local,is_aux1;
1343dcedc2aeSStefano Zampini     ISLocalToGlobalMapping BtoNmap;
1344dcedc2aeSStefano Zampini     PetscInt     *nnz;
1345dcedc2aeSStefano Zampini     PetscInt     *idx_V_B;
1346dcedc2aeSStefano Zampini     PetscInt     *auxindices;
1347dcedc2aeSStefano Zampini     PetscInt     index;
1348dcedc2aeSStefano Zampini     PetscScalar* array2;
1349dcedc2aeSStefano Zampini     MatFactorInfo matinfo;
1350dcedc2aeSStefano Zampini     PetscBool    setsym=PETSC_FALSE,issym=PETSC_FALSE;
1351dcedc2aeSStefano Zampini     /* old variables */
135219fd82e9SBarry Smith     VecType           impVecType;
135319fd82e9SBarry Smith     MatType           impMatType;
13540c7d97c5SJed Brown     PetscInt          n_R=0;
13550c7d97c5SJed Brown     PetscInt          n_D=0;
13560c7d97c5SJed Brown     PetscInt          n_B=0;
13570c7d97c5SJed Brown     PetscScalar       zero=0.0;
13580c7d97c5SJed Brown     PetscScalar       one=1.0;
13590c7d97c5SJed Brown     PetscScalar       m_one=-1.0;
13600c7d97c5SJed Brown     PetscScalar*      array;
13610c7d97c5SJed Brown     PetscScalar       *coarse_submat_vals;
13620c7d97c5SJed Brown     PetscInt          *idx_R_local;
13635b08dc53SStefano Zampini     PetscReal         *coarsefunctions_errors,*constraints_errors;
13640c7d97c5SJed Brown     /* auxiliary indices */
1365aa0d41d4SStefano Zampini     PetscInt          i,j;
1366e269702eSStefano Zampini     /* for verbose output of bddc */
1367e269702eSStefano Zampini     PetscViewer       viewer=pcbddc->dbg_viewer;
13685b08dc53SStefano Zampini     PetscInt          dbg_flag=pcbddc->dbg_flag;
1369a0ba757dSStefano Zampini     /* for counting coarse dofs */
1370534831adSStefano Zampini     PetscInt          n_vertices,n_constraints;
13713b03a366Sstefano_zampini     PetscInt          size_of_constraint;
13723b03a366Sstefano_zampini     PetscInt          *row_cmat_indices;
13733b03a366Sstefano_zampini     PetscScalar       *row_cmat_values;
1374e6872a76SStefano Zampini     PetscInt          *vertices;
13750c7d97c5SJed Brown 
1376a64d13efSStefano Zampini     /* get number of vertices */
1377811e8ca2SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,NULL);CHKERRQ(ierr);
1378a64d13efSStefano Zampini     n_constraints = pcbddc->local_primal_size-n_vertices;
1379dcedc2aeSStefano Zampini     /* Set Non-overlapping dimensions */
1380dcedc2aeSStefano Zampini     n_B = pcis->n_B; n_D = pcis->n - n_B;
1381a64d13efSStefano Zampini     n_R = pcis->n-n_vertices;
1382a64d13efSStefano Zampini 
1383e6872a76SStefano Zampini     /* Set types for local objects needed by BDDC precondtioner */
1384e6872a76SStefano Zampini     impMatType = MATSEQDENSE;
1385e6872a76SStefano Zampini     impVecType = VECSEQ;
1386534831adSStefano Zampini 
13870c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
13880c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
13890c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
13902fa5cd67SKarl Rupp     for (i=0;i<pcis->n;i++) auxindices[i]=i;
13910c7d97c5SJed Brown 
1392e6872a76SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
1393e6872a76SStefano Zampini     /* vertices in boundary numbering */
1394e6872a76SStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
1395e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
1396e6872a76SStefano Zampini     ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
1397e6872a76SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
1398e6872a76SStefano Zampini     if (i != n_vertices) {
1399e6872a76SStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
1400e6872a76SStefano Zampini     }
1401e6872a76SStefano Zampini 
14020c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
14033b03a366Sstefano_zampini     if (n_vertices) {
14040c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
14053b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
14060c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
14070c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
14080c7d97c5SJed Brown     }
1409534831adSStefano Zampini     if (n_constraints) {
141083b7ccabSStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_C,&vec1_C);CHKERRQ(ierr);
141183b7ccabSStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_C,&vec2_C);CHKERRQ(ierr);
14120c7d97c5SJed Brown     }
14130c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14143b03a366Sstefano_zampini     if (n_constraints) {
14150c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14163b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14170c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14180298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,NULL);CHKERRQ(ierr);
14190c7d97c5SJed Brown 
142057a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
1421e6872a76SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
142257a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
142357a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
142457a90decSStefano Zampini 
14250c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14263b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
14273b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
14283b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
142957a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
143057a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14312fa5cd67SKarl Rupp         for (j=0;j<size_of_constraint;j++) array[row_cmat_indices[j]] = -row_cmat_values[j];
143257a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
143357a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
14342fa5cd67SKarl Rupp 
14353b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
143653cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14372fa5cd67SKarl Rupp 
14383b03a366Sstefano_zampini         /* Set values */
14390c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14403b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14410c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14420c7d97c5SJed Brown       }
14430c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14440c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14450c7d97c5SJed Brown 
14460c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14470c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1448d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14493b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14500c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14510c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14520c7d97c5SJed Brown 
14533b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1454d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14553b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14560c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14570298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(M1,NULL);CHKERRQ(ierr);
14583b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
14590c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14600c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14610c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14620c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14630c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14640c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14650c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14663b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14670c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14680c7d97c5SJed Brown       }
14690c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14700c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14710c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
14720c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
14730c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
14740c7d97c5SJed Brown 
14750c7d97c5SJed Brown     }
14760c7d97c5SJed Brown 
14770c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
14783b03a366Sstefano_zampini     if (n_vertices) {
147915aaf578SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr);
1480534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1481534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1482534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
148315aaf578SStefano Zampini       ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
14840c7d97c5SJed Brown     }
14850c7d97c5SJed Brown 
14860c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1487d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
14880c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
14890c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
14900298fd71SBarry Smith     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,NULL);CHKERRQ(ierr);
149129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag ) {
1492d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
14930c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
14940c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
14950298fd71SBarry Smith       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,NULL);CHKERRQ(ierr);
14960c7d97c5SJed Brown     }
14970c7d97c5SJed Brown 
1498e269702eSStefano Zampini     if (dbg_flag) {
1499dcedc2aeSStefano Zampini       ierr = ISGetIndices(is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
15005b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*coarsefunctions_errors),&coarsefunctions_errors);CHKERRQ(ierr);
15015b08dc53SStefano Zampini       ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*constraints_errors),&constraints_errors);CHKERRQ(ierr);
15020c7d97c5SJed Brown     }
15033b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15040c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15050c7d97c5SJed Brown 
15060c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15073b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++){
15080c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15090c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15100c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15110c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15120c7d97c5SJed Brown       /* solution of saddle point problem */
15130bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15140bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15150c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15163b03a366Sstefano_zampini       if (n_constraints) {
15170c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15180c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15190c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15200c7d97c5SJed Brown       }
15210c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15220c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15230c7d97c5SJed Brown 
15240c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15250c7d97c5SJed Brown       /* coarse basis functions */
15260c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15270c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15280c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15290c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15303b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15310c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15320c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
153329622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag  ) {
15340c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15350c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15360c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15373b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15380c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15390c7d97c5SJed Brown       }
15400c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15410c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15422fa5cd67SKarl Rupp       for (j=0; j<n_vertices; j++) coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j];   /* WARNING -> column major ordering */
15430c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15443b03a366Sstefano_zampini       if (n_constraints) {
15450c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15462fa5cd67SKarl 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 */
15470c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15480c7d97c5SJed Brown       }
15490c7d97c5SJed Brown 
1550e269702eSStefano Zampini       if ( dbg_flag ) {
15510c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1552d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15530c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15540c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15552fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
15563b03a366Sstefano_zampini         array[ vertices[i] ] = one;
15570c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15580c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15590c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1560d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
15610c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15620c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15632fa5cd67SKarl Rupp         for (j=0;j<n_vertices;j++) array2[j]=array[j];
15640c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15653b03a366Sstefano_zampini         if (n_constraints) {
15660c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15672fa5cd67SKarl Rupp           for (j=0;j<n_constraints;j++) array2[j+n_vertices]=array[j];
15680c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15690c7d97c5SJed Brown         }
15700c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15710c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
15720c7d97c5SJed Brown         /* check saddle point solution */
1573534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
15743b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
15753b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
15763b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
15770c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15783b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
15790c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15803b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
15810c7d97c5SJed Brown       }
15820c7d97c5SJed Brown     }
15830c7d97c5SJed Brown 
15843b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++){
1585d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
15860c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
15870c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
15880c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
15890c7d97c5SJed Brown       /* solution of saddle point problem */
15900c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
15910c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
15920c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15933b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
15940c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15950c7d97c5SJed Brown       /* coarse basis functions */
15963b03a366Sstefano_zampini       index=i+n_vertices;
15970c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15980c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15990c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16000c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
160153cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16020c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
160329622bf0SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
16040c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16050c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16060c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
160753cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16080c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16090c7d97c5SJed Brown       }
16100c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16113b03a366Sstefano_zampini       if (n_vertices) {
16120c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16132fa5cd67SKarl Rupp         for (j=0; j<n_vertices; j++) coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j]; /* WARNING -> column major ordering */
16140c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16150c7d97c5SJed Brown       }
16160c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16172fa5cd67SKarl 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 */
16180c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16190c7d97c5SJed Brown 
1620e269702eSStefano Zampini       if ( dbg_flag ) {
16210c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
162253cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16230c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16240c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16252fa5cd67SKarl Rupp         for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
16260c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16270c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16280c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
162953cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16300c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16313b03a366Sstefano_zampini         if ( n_vertices) {
16320c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16332fa5cd67SKarl Rupp           for (j=0;j<n_vertices;j++) array2[j]=-array[j];
16340c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16350c7d97c5SJed Brown         }
16360c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16373b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16380c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16390c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16403972b0daSStefano Zampini         /* check saddle point solution */
1641534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16423b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
164353cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16443b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16450c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
164653cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16470c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
164853cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16490c7d97c5SJed Brown       }
16500c7d97c5SJed Brown     }
16510c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16520c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
165329622bf0SStefano Zampini     if ( pcbddc->inexact_prec_type || dbg_flag ) {
16540c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16550c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16560c7d97c5SJed Brown     }
165715aaf578SStefano Zampini     /* compute other basis functions for non-symmetric problems */
165815aaf578SStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
165915aaf578SStefano Zampini     if ( !setsym || (setsym && !issym) ) {
166015aaf578SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
166115aaf578SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
166215aaf578SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
166315aaf578SStefano Zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_B,NULL);CHKERRQ(ierr);
166415aaf578SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag ) {
166515aaf578SStefano Zampini         ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
166615aaf578SStefano Zampini         ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
166715aaf578SStefano Zampini         ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
166815aaf578SStefano Zampini         ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_psi_D,NULL);CHKERRQ(ierr);
166915aaf578SStefano Zampini       }
167015aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
167115aaf578SStefano Zampini         if (n_constraints) {
167215aaf578SStefano Zampini           ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
167315aaf578SStefano Zampini           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
167415aaf578SStefano Zampini           for (j=0;j<n_constraints;j++) {
167515aaf578SStefano Zampini             array[j]=coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i];
167615aaf578SStefano Zampini           }
167715aaf578SStefano Zampini           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
167815aaf578SStefano Zampini         }
167915aaf578SStefano Zampini         if (i<n_vertices) {
168015aaf578SStefano Zampini           ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
168115aaf578SStefano Zampini           ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
168215aaf578SStefano Zampini           ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
168315aaf578SStefano Zampini           ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
168415aaf578SStefano Zampini           ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
168515aaf578SStefano Zampini           if (n_constraints) {
168615aaf578SStefano Zampini             ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
168715aaf578SStefano Zampini           }
168815aaf578SStefano Zampini         } else {
168915aaf578SStefano Zampini           ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
169015aaf578SStefano Zampini         }
169115aaf578SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
169215aaf578SStefano Zampini         ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
169315aaf578SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
169415aaf578SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
169515aaf578SStefano Zampini         ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
169615aaf578SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
169715aaf578SStefano Zampini         ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
169815aaf578SStefano Zampini         if (i<n_vertices) {
169915aaf578SStefano Zampini           ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
170015aaf578SStefano Zampini         }
170115aaf578SStefano Zampini         if ( pcbddc->inexact_prec_type || dbg_flag  ) {
170215aaf578SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
170315aaf578SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
170415aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
170515aaf578SStefano Zampini           ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
170615aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
170715aaf578SStefano Zampini         }
170815aaf578SStefano Zampini 
170915aaf578SStefano Zampini         if ( dbg_flag ) {
171015aaf578SStefano Zampini           /* assemble subdomain vector on nodes */
171115aaf578SStefano Zampini           ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
171215aaf578SStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
171315aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
171415aaf578SStefano Zampini           for (j=0;j<n_R;j++) array[idx_R_local[j]] = array2[j];
171515aaf578SStefano Zampini           if (i<n_vertices) array[vertices[i]] = one;
171615aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
171715aaf578SStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
171815aaf578SStefano Zampini           /* assemble subdomain vector of lagrange multipliers */
171915aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
172015aaf578SStefano Zampini           for (j=0;j<pcbddc->local_primal_size;j++) {
172115aaf578SStefano Zampini             array[j]=-coarse_submat_vals[j*pcbddc->local_primal_size+i];
172215aaf578SStefano Zampini           }
172315aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
172415aaf578SStefano Zampini           /* check saddle point solution */
172515aaf578SStefano Zampini           ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
172615aaf578SStefano Zampini           ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
172715aaf578SStefano Zampini           ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
172815aaf578SStefano Zampini           ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
172915aaf578SStefano Zampini           ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
173015aaf578SStefano Zampini           array[i]=array[i]+m_one; /* shift by the identity matrix */
173115aaf578SStefano Zampini           ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
173215aaf578SStefano Zampini           ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
173315aaf578SStefano Zampini         }
173415aaf578SStefano Zampini       }
173515aaf578SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
173615aaf578SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
173715aaf578SStefano Zampini       if ( pcbddc->inexact_prec_type || dbg_flag ) {
173815aaf578SStefano Zampini         ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
173915aaf578SStefano Zampini         ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
174015aaf578SStefano Zampini       }
174115aaf578SStefano Zampini     }
174215aaf578SStefano Zampini     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17430c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
174415aaf578SStefano Zampini     /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
174515aaf578SStefano Zampini     /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
17469d2fce94SStefano Zampini     if (dbg_flag) {
17470c7d97c5SJed Brown       Mat         coarse_sub_mat;
17480c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
174915aaf578SStefano Zampini       Mat         coarse_phi_D,coarse_phi_B;
175015aaf578SStefano Zampini       Mat         coarse_psi_D,coarse_psi_B;
175115aaf578SStefano Zampini       Mat         A_II,A_BB,A_IB,A_BI;
175219fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
17535b08dc53SStefano Zampini       PetscReal   real_value;
17540c7d97c5SJed Brown 
1755c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1756c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1757c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1758c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1759c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1760c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
176115aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
176215aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
176315aaf578SStefano Zampini         ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
176415aaf578SStefano Zampini       }
1765c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
17660c7d97c5SJed Brown 
17670c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
17680c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
17690c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
177015aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
177115aaf578SStefano Zampini         ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
177215aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
177315aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
177415aaf578SStefano Zampini         ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
177515aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
177615aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
177715aaf578SStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
177815aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
177915aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
178015aaf578SStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
178115aaf578SStefano Zampini         ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
178215aaf578SStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
178315aaf578SStefano Zampini       } else {
178453cdbc3dSStefano Zampini         ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
178553cdbc3dSStefano Zampini         ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
178653cdbc3dSStefano Zampini         ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1787c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
178853cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
178953cdbc3dSStefano Zampini         ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1790c042a7c3SStefano Zampini         ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
179153cdbc3dSStefano Zampini         ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
179215aaf578SStefano Zampini       }
179353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
179453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
179553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
179615aaf578SStefano Zampini       ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
179715aaf578SStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
17985b08dc53SStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
17990c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
18000c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
18015b08dc53SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
180215aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
180315aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
180415aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
180515aaf578SStefano Zampini       }
180615aaf578SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
180715aaf578SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
180815aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
180915aaf578SStefano Zampini       }
181015aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
181115aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
181215aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
181315aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
181415aaf578SStefano Zampini         }
181515aaf578SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
181615aaf578SStefano Zampini         for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
181715aaf578SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
181815aaf578SStefano Zampini         }
181915aaf578SStefano Zampini       }
18200c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
182153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
182253cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
182353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
182453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
182553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
182653cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
182753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
182853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
182953cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
183053cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
183115aaf578SStefano Zampini       if (pcbddc->coarse_psi_B) {
183215aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
183315aaf578SStefano Zampini         ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
183415aaf578SStefano Zampini       }
183515aaf578SStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
1836dcedc2aeSStefano Zampini       ierr = ISRestoreIndices(is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
18370c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
18380c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
18390c7d97c5SJed Brown     }
18400c7d97c5SJed Brown     /* free memory */
18413b03a366Sstefano_zampini     if (n_vertices) {
184215aaf578SStefano Zampini       ierr = PetscFree(vertices);CHKERRQ(ierr);
18430c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
18440c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
18450c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
18460c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
18470c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
18480c7d97c5SJed Brown     }
1849534831adSStefano Zampini     if (n_constraints) {
18500c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
18510c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
18520c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
18530c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
18540c7d97c5SJed Brown     }
1855a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
1856a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1857a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
1858674ae819SStefano Zampini     ierr = PCBDDCSetUpCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
1859a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
18600c7d97c5SJed Brown   }
18610c7d97c5SJed Brown   /* free memory */
18620c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1863674ae819SStefano Zampini 
18640c7d97c5SJed Brown   PetscFunctionReturn(0);
18650c7d97c5SJed Brown }
18660c7d97c5SJed Brown 
18670c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
18680c7d97c5SJed Brown 
18697cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
18707cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
18717cbb387bSStefano Zampini #include "metis.h"
18727cbb387bSStefano Zampini #define MetisInt    idx_t
18737cbb387bSStefano Zampini #define MetisScalar real_t
18747cbb387bSStefano Zampini #endif
18757cbb387bSStefano Zampini 
18760c7d97c5SJed Brown #undef __FUNCT__
1877674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
1878674ae819SStefano Zampini static PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
18790c7d97c5SJed Brown {
1880674ae819SStefano Zampini 
1881674ae819SStefano Zampini 
18820c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
18830c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
18840c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1885ce94432eSBarry Smith   MPI_Comm  prec_comm;
18860c7d97c5SJed Brown   MPI_Comm  coarse_comm;
18870c7d97c5SJed Brown 
1888674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1889674ae819SStefano Zampini 
18900c7d97c5SJed Brown   /* common to all choiches */
18910c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
18920c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
18930c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
18940c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
18950c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
18960c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
18970c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
18980c7d97c5SJed Brown   PetscMPIInt master_proc=0;
18990c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
19000c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
19015b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
19020c7d97c5SJed Brown   PetscMPIInt count_recv=0;
19035b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
19040c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
19050c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
19060c7d97c5SJed Brown   /* some other variables */
19070c7d97c5SJed Brown   PetscErrorCode ierr;
190819fd82e9SBarry Smith   MatType coarse_mat_type;
190919fd82e9SBarry Smith   PCType  coarse_pc_type;
191019fd82e9SBarry Smith   KSPType coarse_ksp_type;
191153cdbc3dSStefano Zampini   PC pc_temp;
19124fad6a16SStefano Zampini   PetscInt i,j,k;
19133b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1914e269702eSStefano Zampini   /* verbose output viewer */
1915e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
19165b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
1917142dfd88SStefano Zampini 
1918ea7e1babSStefano Zampini   PetscInt      offset,offset2;
1919a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
1920523858cfSStefano Zampini   PetscInt      *dnz,*onz;
1921142dfd88SStefano Zampini 
1922142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
19230c7d97c5SJed Brown 
19240c7d97c5SJed Brown   PetscFunctionBegin;
19254b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
19260c7d97c5SJed Brown   ins_local_primal_indices = 0;
19270c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
19280c7d97c5SJed Brown   localsizes2              = 0;
19290c7d97c5SJed Brown   localdispl2              = 0;
19300c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
19310c7d97c5SJed Brown   coarse_ISLG              = 0;
19320c7d97c5SJed Brown 
193353cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
193453cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
1935142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
1936142dfd88SStefano Zampini 
1937beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1938beed3852SStefano Zampini   {
1939674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
1940ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
1941ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
1942ef028eecSStefano Zampini 
1943ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1944beed3852SStefano Zampini 
1945beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1946ffe5efe1SStefano Zampini     j = 0;
1947142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1948ffe5efe1SStefano Zampini       j = size_prec_comm;
1949ffe5efe1SStefano Zampini     }
1950ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1951ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1952beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
1953142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
19545619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1955ffe5efe1SStefano Zampini     } else {
1956ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1957ffe5efe1SStefano Zampini     }
1958beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1959ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
1960beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1961beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1962beed3852SStefano Zampini     }
1963beed3852SStefano Zampini 
1964da1bb401SStefano Zampini     /* First let's count coarse dofs.
1965beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1966beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1967beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1968ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
1969674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
1970674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
1971674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1972674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
1973674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
1974674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1975ef028eecSStefano Zampini     /* Compute number of coarse dofs */
1976674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
1977ef028eecSStefano Zampini 
1978ef028eecSStefano Zampini     if (dbg_flag) {
19792e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
19802e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
19812e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
19822e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
19832e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
19842fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
1985beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
19862e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1987da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1988da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1989da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1990da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1991da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
19922e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
19932e8d2280SStefano Zampini         if (array[i] == 1.0) {
19942e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
19952e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
19962e8d2280SStefano Zampini         }
19972e8d2280SStefano Zampini       }
19982e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
19992e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
20005b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
20012e8d2280SStefano Zampini       }
2002da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20032e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2004da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2005da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2006da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
20072e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
20082e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20092e8d2280SStefano Zampini     }
2010142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
20110bdf917eSStefano Zampini   }
20120bdf917eSStefano Zampini 
20132e8d2280SStefano Zampini   if (dbg_flag) {
20147cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
20159d9e44b6SStefano Zampini     if (dbg_flag > 1) {
2016674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
20172e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2018674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2019674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
2020674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
2021674ae819SStefano Zampini       }
20222e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20232e8d2280SStefano Zampini     }
20242e8d2280SStefano Zampini   }
20252e8d2280SStefano Zampini 
2026a929c220SStefano Zampini   im_active = 0;
20272fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
2028a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
20290bdf917eSStefano Zampini 
20300bdf917eSStefano Zampini   /* adapt coarse problem type */
20317cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
20324fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20334fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2034a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
20350bdf917eSStefano Zampini         if (dbg_flag) {
2036a929c220SStefano 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);
20370bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20380bdf917eSStefano Zampini         }
20390bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2040142dfd88SStefano Zampini       }
20414fad6a16SStefano Zampini     } else {
20424fad6a16SStefano Zampini       if (dbg_flag) {
2043a929c220SStefano 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);
20444fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20454fad6a16SStefano Zampini       }
20464fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
20474fad6a16SStefano Zampini     }
20484fad6a16SStefano Zampini   }
20497cbb387bSStefano Zampini #else
20507cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
20517cbb387bSStefano Zampini #endif
2052beed3852SStefano Zampini 
20530c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
20540c7d97c5SJed Brown 
2055da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
20560c7d97c5SJed Brown     {
20577cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
20580c7d97c5SJed Brown       /* we need additional variables */
20590c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
20600c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
20610c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
20620c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
20630c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
20640c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
20650c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
20660c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
20670c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
20680c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
20690c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
20700c7d97c5SJed Brown       MetisInt    *faces_adjncy;
20710c7d97c5SJed Brown       MetisInt    *faces_xadj;
20720c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
20730c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
20740c7d97c5SJed Brown       PetscInt    *array_int;
20750c7d97c5SJed Brown       PetscMPIInt my_faces=0;
20760c7d97c5SJed Brown       PetscMPIInt total_faces=0;
20773828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
20780c7d97c5SJed Brown 
20790c7d97c5SJed Brown       /* define some quantities */
20800c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
20810c7d97c5SJed Brown       coarse_mat_type = MATIS;
20820c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
2083142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
20840c7d97c5SJed Brown 
20850c7d97c5SJed Brown       /* details of coarse decomposition */
2086a929c220SStefano Zampini       n_subdomains = active_procs;
20870c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2088a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
20893828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
20903828260eSStefano Zampini 
2091a929c220SStefano Zampini #if 0
2092a929c220SStefano Zampini       PetscMPIInt *old_ranks;
2093a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2094a929c220SStefano Zampini       MatPartitioning mat_part;
2095a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2096a929c220SStefano Zampini       PetscViewer viewer_test;
2097a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
2098a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
2099a929c220SStefano Zampini       Mat         mat_adj;
2100a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2101a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2102a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2103a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2104a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2105a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2106a929c220SStefano Zampini       if (im_active) {
2107a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2108a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2109a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2110a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2111a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2112674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2113674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2114a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2115a929c220SStefano Zampini         k = pcis->n_neigh-1;
2116a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2117a929c220SStefano Zampini         ii[0]=0;
2118a929c220SStefano Zampini         ii[1]=k;
2119a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2120674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2121a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
21220298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2123a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2124a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2125a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2126a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2127a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2128a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2129a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2130a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2131a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2132a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2133a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2134a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2135a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2136a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2137a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2138a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2139a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2140a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2141a929c220SStefano Zampini       }
2142a929c220SStefano Zampini #endif
2143a929c220SStefano Zampini 
21444fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
21450c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
21463828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
21470c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
21480c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
21490c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
21500c7d97c5SJed Brown         }
21510c7d97c5SJed Brown       }
21520c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
21530c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
21547cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
21550c7d97c5SJed Brown             my_faces++;
21560c7d97c5SJed Brown             break;
21570c7d97c5SJed Brown           }
21580c7d97c5SJed Brown         }
21590c7d97c5SJed Brown       }
21600c7d97c5SJed Brown 
216153cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
21620c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
21630c7d97c5SJed Brown       my_faces=0;
21640c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
21650c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
21667cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
21670c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
21680c7d97c5SJed Brown             my_faces++;
21690c7d97c5SJed Brown             break;
21700c7d97c5SJed Brown           }
21710c7d97c5SJed Brown         }
21720c7d97c5SJed Brown       }
21730c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
21740c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
21750c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
21760c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
21770c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
21780c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
21790c7d97c5SJed Brown       }
218053cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21810c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
21820c7d97c5SJed Brown         faces_xadj[0]=0;
21830c7d97c5SJed Brown         faces_displacements[0]=0;
21840c7d97c5SJed Brown         j=0;
21850c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
21860c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
21870c7d97c5SJed Brown           if (number_of_faces[i-1]) {
21880c7d97c5SJed Brown             j++;
21890c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
21900c7d97c5SJed Brown           }
21910c7d97c5SJed Brown         }
21920c7d97c5SJed Brown       }
219353cdbc3dSStefano 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);
21940c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
21950c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
21960c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
21973828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
21980c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
21990c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
22000c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
22010c7d97c5SJed Brown       }
22020c7d97c5SJed Brown 
22030c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
2204674ae819SStefano Zampini 
22053828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
2206674ae819SStefano Zampini 
22070c7d97c5SJed Brown         ncon=1;
22080c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
22090c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
22100c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
22110c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
22120c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
22130c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
22140c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
22154fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
22163828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
22173828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
22183828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
22190c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2220674ae819SStefano 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);
22213828260eSStefano Zampini           } else {
22223828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2223674ae819SStefano 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);
22243828260eSStefano Zampini           }
22254fad6a16SStefano Zampini         } else {
22262fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
22274fad6a16SStefano Zampini         }
22280c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
22290c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
22300bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
22312fa5cd67SKarl Rupp 
22320c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
22332fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
22342fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
22350c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
22360c7d97c5SJed Brown       }
22370c7d97c5SJed Brown 
22380c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
22390c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2240da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2241da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
22420c7d97c5SJed Brown       }
2243da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2244da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
224553cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
22460c7d97c5SJed Brown 
22470c7d97c5SJed Brown       if ( coarse_color == 0 ) {
224853cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
224953cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
22500c7d97c5SJed Brown       } else {
22510c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
22520c7d97c5SJed Brown       }
22530c7d97c5SJed Brown 
22547cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
22550c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
22560c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
22570bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
22580bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
22590c7d97c5SJed Brown         /* some initializations */
22600c7d97c5SJed Brown         displacements_recv[0]=0;
22610bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
22620c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
22630bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
22640bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
22652fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
22660bdf917eSStefano Zampini           }
22670bdf917eSStefano Zampini         }
22680c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
22692fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
22702fa5cd67SKarl Rupp 
22710c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
22720c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
22730c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
22743828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
22750c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
22760c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
22773828260eSStefano Zampini               total_count_recv[j]+=1;
22780c7d97c5SJed Brown             }
22790c7d97c5SJed Brown           }
22800c7d97c5SJed Brown         }
2281da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
22823828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
22833828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
22843828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
22853828260eSStefano Zampini           }
22863828260eSStefano Zampini           printf("\n");
2287da1bb401SStefano Zampini         }*/
22880c7d97c5SJed Brown 
22890c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
22900bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
22910bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
22920bdf917eSStefano Zampini         }
2293da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2294674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
22953828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
22963828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
22973828260eSStefano Zampini           } else {
22983828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
22993828260eSStefano Zampini           }
2300da1bb401SStefano Zampini         printf("\n");*/
23010c7d97c5SJed Brown       }
23020c7d97c5SJed Brown 
23030c7d97c5SJed Brown       /* Scatter new decomposition for send details */
230453cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
23050c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
23060c7d97c5SJed Brown       if ( coarse_color == 0) {
230753cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
23080c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
230953cdbc3dSStefano 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);
23100c7d97c5SJed Brown       }
23110c7d97c5SJed Brown 
2312da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2313da1bb401SStefano Zampini       if (coarse_color == 0) {
2314da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2315da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
2316da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2317da1bb401SStefano Zampini         printf("\n");
2318da1bb401SStefano Zampini       }*/
23190c7d97c5SJed Brown 
23200c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
23210bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2322da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
23230bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
23240c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
23250c7d97c5SJed Brown       }
23267cbb387bSStefano Zampini #endif
23270c7d97c5SJed Brown       break;
23280c7d97c5SJed Brown     }
23290c7d97c5SJed Brown 
23300c7d97c5SJed Brown     case(REPLICATED_BDDC):
23310c7d97c5SJed Brown 
23320c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
23330c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
23340c7d97c5SJed Brown       coarse_pc_type  = PCLU;
233553cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
23360c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
23370c7d97c5SJed Brown       active_rank = rank_prec_comm;
23380c7d97c5SJed Brown       break;
23390c7d97c5SJed Brown 
23400c7d97c5SJed Brown     case(PARALLEL_BDDC):
23410c7d97c5SJed Brown 
23420c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2343674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
23440c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
234553cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
23460c7d97c5SJed Brown       coarse_comm = prec_comm;
23470c7d97c5SJed Brown       active_rank = rank_prec_comm;
23480c7d97c5SJed Brown       break;
23490c7d97c5SJed Brown 
23500c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
23510c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
2352674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
23530c7d97c5SJed Brown       coarse_pc_type = PCLU;
235453cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
23550c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
23560c7d97c5SJed Brown       active_rank = master_proc;
23570c7d97c5SJed Brown       break;
23580c7d97c5SJed Brown   }
23590c7d97c5SJed Brown 
23600c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
23610c7d97c5SJed Brown 
23620c7d97c5SJed Brown     case(SCATTERS_BDDC):
23630c7d97c5SJed Brown       {
23640c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
23650c7d97c5SJed Brown 
23662e8d2280SStefano Zampini           IS coarse_IS;
23672e8d2280SStefano Zampini 
2368523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2369523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2370523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
2371523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2372523858cfSStefano Zampini             /* nonzeros */
2373523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2374523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2375523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2376523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
2377523858cfSStefano Zampini             }
2378523858cfSStefano Zampini           } else {
23790c7d97c5SJed Brown             PetscMPIInt send_size;
2380ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
23810c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
23820c7d97c5SJed Brown             PetscInt    ii,jj;
23830c7d97c5SJed Brown             MPI_Request *requests;
2384ef028eecSStefano Zampini 
2385523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2386523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
2387523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
2388523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
2389523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
2390523858cfSStefano Zampini             j = 0;
2391523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2392523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
2393523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
2394523858cfSStefano Zampini             }
2395523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
2396523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23970c7d97c5SJed Brown             /* allocate auxiliary space */
2398523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23990c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
24000c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
24010c7d97c5SJed Brown             /* allocate stuffs for message massing */
24020c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2403523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2404523858cfSStefano Zampini             /* send indices to be inserted */
2405523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2406523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
2407523858cfSStefano 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);
2408523858cfSStefano Zampini             }
2409523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2410523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
2411ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2412ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
2413ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
2414ef028eecSStefano Zampini               }
2415ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2416523858cfSStefano Zampini             }
2417523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2418ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2419ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2420ef028eecSStefano Zampini             }
24210c7d97c5SJed Brown             j = 0;
24220c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
24232e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
24242e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
24250c7d97c5SJed Brown               localdispl2[i] = j;
24260c7d97c5SJed Brown               j += localsizes2[i];
2427523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
24284fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
24292e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
24304fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
24310c7d97c5SJed Brown               }
24324fad6a16SStefano Zampini             }
2433523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
24340c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
24350c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
24360c7d97c5SJed Brown             ins_local_primal_size = 0;
2437ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
2438ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
24390c7d97c5SJed Brown                 ins_local_primal_size++;
2440ea7e1babSStefano Zampini               }
2441ea7e1babSStefano Zampini             }
24420c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
24430c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
24440c7d97c5SJed Brown             j = 0;
2445ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
2446ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
24472e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
24482e8d2280SStefano Zampini                 j++;
2449ea7e1babSStefano Zampini               }
2450ea7e1babSStefano Zampini             }
2451523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2452523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
2453523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2454523858cfSStefano Zampini             }
2455523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2456523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2457523858cfSStefano 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);
2458523858cfSStefano Zampini             }
2459523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2460523858cfSStefano Zampini             /* nonzeros */
2461523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2462523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
24630c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
24640c7d97c5SJed Brown             j=0;
24650c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
24660c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
24670c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
24680c7d97c5SJed Brown               } else {
24690c7d97c5SJed Brown                 aux_ins_indices[i]=j;
24700c7d97c5SJed Brown                 j++;
24710c7d97c5SJed Brown               }
24720c7d97c5SJed Brown             }
24734fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
2474523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
2475523858cfSStefano Zampini               for (k=0;k<j;k++) {
2476523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
24770c7d97c5SJed Brown               }
24780c7d97c5SJed Brown             }
2479523858cfSStefano Zampini             /* check */
2480523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2481523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2482523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
24830c7d97c5SJed Brown               }
24840c7d97c5SJed Brown             }
24850c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
24860c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
24870c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
24884fad6a16SStefano Zampini           }
24890c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
2490142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
24910c7d97c5SJed Brown           coarse_comm = prec_comm;
24920c7d97c5SJed Brown           active_rank = rank_prec_comm;
24930c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
24940c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
24950c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
24962e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
24970c7d97c5SJed Brown           /* arrays for values insertion */
24980c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
24992e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
25000c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
25010c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
25020c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
25034fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
25044fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
25054fad6a16SStefano Zampini             }
25060c7d97c5SJed Brown           }
25070c7d97c5SJed Brown         }
25080c7d97c5SJed Brown         break;
2509674ae819SStefano Zampini 
25100c7d97c5SJed Brown     }
25110c7d97c5SJed Brown 
25120c7d97c5SJed Brown     case(GATHERS_BDDC):
25130c7d97c5SJed Brown       {
2514674ae819SStefano Zampini 
25150c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
2516ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
25170c7d97c5SJed Brown 
25180c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
25190c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
25200bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
25210c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
25220c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
25230c7d97c5SJed Brown           /* arrays for values insertion */
25242fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
25250c7d97c5SJed Brown           localdispl2[0]=0;
25262fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
25270c7d97c5SJed Brown           j=0;
25282fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
25290c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
25300c7d97c5SJed Brown         }
25310c7d97c5SJed Brown 
25320c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
25330c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
2534ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
25352fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
25362fa5cd67SKarl Rupp 
25370c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
2538ef028eecSStefano 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);
253953cdbc3dSStefano 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);
25400c7d97c5SJed Brown         } else {
2541ef028eecSStefano 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);
254253cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
25430c7d97c5SJed Brown         }
2544ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
25450c7d97c5SJed Brown         break;
2546da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
25470c7d97c5SJed Brown   }
25480c7d97c5SJed Brown 
25490c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
25500c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2551142dfd88SStefano Zampini 
2552142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2553142dfd88SStefano Zampini 
25540c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
25550c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
25560c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
25570c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2558674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2559674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
25603b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2561da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
25623b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
25630c7d97c5SJed Brown     } else {
25644fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
25653b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
25660c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2567674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2568674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
25693b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2570da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2571a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
25720c7d97c5SJed Brown     }
2573142dfd88SStefano Zampini     /* preallocation */
2574142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2575ef028eecSStefano Zampini 
2576674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2577ef028eecSStefano Zampini 
2578142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2579142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2580674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2581ef028eecSStefano Zampini 
2582142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2583ef028eecSStefano Zampini 
2584ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2585ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2586ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2587ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2588ef028eecSStefano Zampini 
2589ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2590674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2591ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2592ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2593ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2594ef028eecSStefano Zampini 
2595ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2596ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2597ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2598ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2599ef028eecSStefano Zampini 
2600ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2601ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2602142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2603ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2604ef028eecSStefano Zampini             row_ownership[j]=i;
2605142dfd88SStefano Zampini           }
2606142dfd88SStefano Zampini         }
2607ef028eecSStefano Zampini 
2608ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2609ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2610ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2611ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2612ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2613ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2614ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2615ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2616142dfd88SStefano Zampini             } else {
2617ef028eecSStefano Zampini               my_onz[i] += 1.0;
2618142dfd88SStefano Zampini             }
2619ef028eecSStefano Zampini             if (i != j) {
2620ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2621ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2622ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2623142dfd88SStefano Zampini               } else {
2624ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2625142dfd88SStefano Zampini               }
2626142dfd88SStefano Zampini             }
2627142dfd88SStefano Zampini           }
2628142dfd88SStefano Zampini         }
2629ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2630ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2631a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2632ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2633ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2634a929c220SStefano Zampini         }
2635ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2636ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2637ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2638ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2639ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2640ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
26415b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
26422fa5cd67SKarl Rupp 
2643ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2644ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
26455b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
26462fa5cd67SKarl Rupp 
2647ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2648ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2649ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2650ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2651ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2652ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2653142dfd88SStefano Zampini       } else {
2654142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2655142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2656142dfd88SStefano Zampini           offset2=localdispl2[k];
2657142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2658ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2659ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2660ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2661ef028eecSStefano Zampini           }
2662142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2663142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2664142dfd88SStefano Zampini           }
2665ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2666142dfd88SStefano Zampini         }
2667142dfd88SStefano Zampini       }
26682fa5cd67SKarl Rupp 
2669142dfd88SStefano Zampini       /* check */
2670142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
26712fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
26722fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2673142dfd88SStefano Zampini       }
2674d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2675d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2676142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2677142dfd88SStefano Zampini     } else {
2678523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2679523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2680142dfd88SStefano Zampini     }
2681142dfd88SStefano Zampini     /* insert values */
2682523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
26830c7d97c5SJed 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);
2684523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2685523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2686523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2687523858cfSStefano 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);
2688523858cfSStefano Zampini       } else {
2689523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2690523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2691523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2692523858cfSStefano Zampini           offset2 = localdispl2[k];
2693523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2694ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2695ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2696ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2697ef028eecSStefano Zampini           }
2698523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2699523858cfSStefano 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);
2700ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2701523858cfSStefano Zampini         }
2702523858cfSStefano Zampini       }
2703523858cfSStefano Zampini       ins_local_primal_indices = 0;
2704523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2705ea7e1babSStefano Zampini     } else {
2706ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2707ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2708ea7e1babSStefano Zampini         offset2=localdispl2[k];
2709ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2710ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2711ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2712ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2713ef028eecSStefano Zampini         }
2714ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2715ea7e1babSStefano 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);
2716ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2717ea7e1babSStefano Zampini       }
2718ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2719ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2720ea7e1babSStefano Zampini     }
27210c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27220c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2723142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2724142dfd88SStefano Zampini     if (issym) {
2725142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2726142dfd88SStefano Zampini     }
27270c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
27280bdf917eSStefano Zampini   }
27290bdf917eSStefano Zampini 
27300bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
27310bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
27320bdf917eSStefano Zampini      IS local_IS,global_IS;
27330bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
27340bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
27350bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
27360bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
27370bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
27380bdf917eSStefano Zampini   }
27390bdf917eSStefano Zampini 
2740a929c220SStefano Zampini   /* free memory no longer needed */
2741a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2742a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2743a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2744a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2745a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2746a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2747a929c220SStefano Zampini 
2748674ae819SStefano Zampini   /* Compute coarse null space */
2749674ae819SStefano Zampini   CoarseNullSpace = 0;
27500bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2751674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
27520bdf917eSStefano Zampini   }
27530bdf917eSStefano Zampini 
27540bdf917eSStefano Zampini   /* KSP for coarse problem */
27550bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
27562e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
27570bdf917eSStefano Zampini 
275853cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
275953cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
276053cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
27613b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
276253cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
276353cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
276453cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
27650c7d97c5SJed Brown     /* Allow user's customization */
2766da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
27670c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
276853cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
27694fad6a16SStefano Zampini       i = pcbddc->current_level+1;
27704fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
27714fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
27724fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
277353cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2774674ae819SStefano Zampini       if (CoarseNullSpace) {
2775674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2776674ae819SStefano Zampini       }
27774fad6a16SStefano Zampini       if (dbg_flag) {
27784fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
27794fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
278053cdbc3dSStefano Zampini       }
2781674ae819SStefano Zampini     } else {
2782674ae819SStefano Zampini       if (CoarseNullSpace) {
2783674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2784674ae819SStefano Zampini       }
27854fad6a16SStefano Zampini     }
27864fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
278753cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2788142dfd88SStefano Zampini 
27890298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
27902e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
27912e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
27922e8d2280SStefano Zampini     if (j == 1) {
27932e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
27942e8d2280SStefano Zampini       if (isbddc) {
27952e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
27965619798eSStefano Zampini       }
27975619798eSStefano Zampini     }
27980c7d97c5SJed Brown   }
2799a929c220SStefano Zampini   /* Check coarse problem if requested */
2800142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2801142dfd88SStefano Zampini     KSP check_ksp;
2802142dfd88SStefano Zampini     PC  check_pc;
2803142dfd88SStefano Zampini     Vec check_vec;
2804142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
280519fd82e9SBarry Smith     KSPType check_ksp_type;
28060c7d97c5SJed Brown 
2807142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2808142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2809142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
28100bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2811142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
28122fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
28132fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2814142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2815142dfd88SStefano Zampini     } else {
2816142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2817142dfd88SStefano Zampini     }
2818142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2819142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2820142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2821142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2822142dfd88SStefano Zampini     /* create random vec */
2823142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
28240298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2825674ae819SStefano Zampini     if (CoarseNullSpace) {
28261cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
2827674ae819SStefano Zampini     }
2828142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2829142dfd88SStefano Zampini     /* solve coarse problem */
2830142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2831674ae819SStefano Zampini     if (CoarseNullSpace) {
28321cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
2833674ae819SStefano Zampini     }
2834142dfd88SStefano Zampini     /* check coarse problem residual error */
2835142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2836142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2837142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2838142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2839142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2840142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2841142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2842142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2843142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2844142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2845e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
28463b03a366Sstefano_zampini     }
2847142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2848142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2849142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
285053cdbc3dSStefano Zampini   }
2851674ae819SStefano Zampini   if (dbg_flag) {
2852da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2853da1bb401SStefano Zampini   }
2854674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2855a0ba757dSStefano Zampini 
28560c7d97c5SJed Brown   PetscFunctionReturn(0);
28570c7d97c5SJed Brown }
28580c7d97c5SJed Brown 
2859