xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 99cc79942c21604d54afc55692e4e3e15e4ade67)
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 */
27*99cc7994SStefano Zampini static PetscErrorCode PCBDDCSetUpSolvers(PC);
28674ae819SStefano Zampini 
290c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
300c7d97c5SJed Brown #undef __FUNCT__
310c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
320c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
330c7d97c5SJed Brown {
340c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
350c7d97c5SJed Brown   PetscErrorCode ierr;
360c7d97c5SJed Brown 
370c7d97c5SJed Brown   PetscFunctionBegin;
380c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
390c7d97c5SJed Brown   /* Verbose debugging of main data structures */
409d9e44b6SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,NULL);CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Some customization for default primal space */
420298fd71SBarry 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);
430298fd71SBarry 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);
440298fd71SBarry 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);
450298fd71SBarry 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);
460c7d97c5SJed Brown   /* Coarse solver context */
476c667b0aSStefano 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 */
480298fd71SBarry 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);
490c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
500298fd71SBarry 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);
51674ae819SStefano 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);
52674ae819SStefano 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);
53674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
54674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
55674ae819SStefano Zampini   }
560298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
570298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
58674ae819SStefano 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);
590c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
600c7d97c5SJed Brown   PetscFunctionReturn(0);
610c7d97c5SJed Brown }
620c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
63674ae819SStefano Zampini #undef __FUNCT__
64674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
65674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
66674ae819SStefano Zampini {
67674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
68674ae819SStefano Zampini   PetscErrorCode ierr;
691e6b0712SBarry Smith 
70674ae819SStefano Zampini   PetscFunctionBegin;
71674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
72674ae819SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
73674ae819SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
74674ae819SStefano Zampini   PetscFunctionReturn(0);
75674ae819SStefano Zampini }
76674ae819SStefano Zampini #undef __FUNCT__
77674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
78674ae819SStefano Zampini /*@
79674ae819SStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC.
80674ae819SStefano Zampini 
81674ae819SStefano Zampini    Not collective
82674ae819SStefano Zampini 
83674ae819SStefano Zampini    Input Parameters:
84674ae819SStefano Zampini +  pc - the preconditioning context
85674ae819SStefano Zampini -  PrimalVertices - index sets of primal vertices in local numbering
86674ae819SStefano Zampini 
87674ae819SStefano Zampini    Level: intermediate
88674ae819SStefano Zampini 
89674ae819SStefano Zampini    Notes:
90674ae819SStefano Zampini 
91674ae819SStefano Zampini .seealso: PCBDDC
92674ae819SStefano Zampini @*/
93674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
94674ae819SStefano Zampini {
95674ae819SStefano Zampini   PetscErrorCode ierr;
96674ae819SStefano Zampini 
97674ae819SStefano Zampini   PetscFunctionBegin;
98674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
99674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
100674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
101674ae819SStefano Zampini   PetscFunctionReturn(0);
102674ae819SStefano Zampini }
103674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
1040c7d97c5SJed Brown #undef __FUNCT__
1050c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
10653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
1070c7d97c5SJed Brown {
1080c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1090c7d97c5SJed Brown 
1100c7d97c5SJed Brown   PetscFunctionBegin;
1110c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
1120c7d97c5SJed Brown   PetscFunctionReturn(0);
1130c7d97c5SJed Brown }
1141e6b0712SBarry Smith 
1150c7d97c5SJed Brown #undef __FUNCT__
1160c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
11753cdbc3dSStefano Zampini /*@
1189c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
11953cdbc3dSStefano Zampini 
1209c0446d6SStefano Zampini    Not collective
12153cdbc3dSStefano Zampini 
12253cdbc3dSStefano Zampini    Input Parameters:
12353cdbc3dSStefano Zampini +  pc - the preconditioning context
12453cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
12553cdbc3dSStefano Zampini 
12653cdbc3dSStefano Zampini    Level: intermediate
12753cdbc3dSStefano Zampini 
12853cdbc3dSStefano Zampini    Notes:
129da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
13053cdbc3dSStefano Zampini 
13153cdbc3dSStefano Zampini .seealso: PCBDDC
13253cdbc3dSStefano Zampini @*/
1330c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
1340c7d97c5SJed Brown {
1350c7d97c5SJed Brown   PetscErrorCode ierr;
1360c7d97c5SJed Brown 
1370c7d97c5SJed Brown   PetscFunctionBegin;
1380c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1390c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
1400c7d97c5SJed Brown   PetscFunctionReturn(0);
1410c7d97c5SJed Brown }
1420c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1430c7d97c5SJed Brown #undef __FUNCT__
1444fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
1454fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
1464fad6a16SStefano Zampini {
1474fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1484fad6a16SStefano Zampini 
1494fad6a16SStefano Zampini   PetscFunctionBegin;
1504fad6a16SStefano Zampini   pcbddc->coarsening_ratio=k;
1514fad6a16SStefano Zampini   PetscFunctionReturn(0);
1524fad6a16SStefano Zampini }
1531e6b0712SBarry Smith 
1544fad6a16SStefano Zampini #undef __FUNCT__
1554fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
1564fad6a16SStefano Zampini /*@
1574fad6a16SStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
1584fad6a16SStefano Zampini 
1594fad6a16SStefano Zampini    Logically collective on PC
1604fad6a16SStefano Zampini 
1614fad6a16SStefano Zampini    Input Parameters:
1624fad6a16SStefano Zampini +  pc - the preconditioning context
1634fad6a16SStefano Zampini -  k - coarsening ratio
1644fad6a16SStefano Zampini 
1654fad6a16SStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
1664fad6a16SStefano Zampini 
1674fad6a16SStefano Zampini    Level: intermediate
1684fad6a16SStefano Zampini 
1694fad6a16SStefano Zampini    Notes:
1704fad6a16SStefano Zampini 
1714fad6a16SStefano Zampini .seealso: PCBDDC
1724fad6a16SStefano Zampini @*/
1734fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
1744fad6a16SStefano Zampini {
1754fad6a16SStefano Zampini   PetscErrorCode ierr;
1764fad6a16SStefano Zampini 
1774fad6a16SStefano Zampini   PetscFunctionBegin;
1784fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1794fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
1804fad6a16SStefano Zampini   PetscFunctionReturn(0);
1814fad6a16SStefano Zampini }
1824fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1831e6b0712SBarry Smith 
1844fad6a16SStefano Zampini #undef __FUNCT__
1854fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
1864fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
1874fad6a16SStefano Zampini {
1884fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1894fad6a16SStefano Zampini 
1904fad6a16SStefano Zampini   PetscFunctionBegin;
1914fad6a16SStefano Zampini   pcbddc->max_levels=max_levels;
1924fad6a16SStefano Zampini   PetscFunctionReturn(0);
1934fad6a16SStefano Zampini }
1941e6b0712SBarry Smith 
1954fad6a16SStefano Zampini #undef __FUNCT__
1964fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels"
1974fad6a16SStefano Zampini /*@
1984fad6a16SStefano Zampini  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
1994fad6a16SStefano Zampini 
2004fad6a16SStefano Zampini    Logically collective on PC
2014fad6a16SStefano Zampini 
2024fad6a16SStefano Zampini    Input Parameters:
2034fad6a16SStefano Zampini +  pc - the preconditioning context
2044fad6a16SStefano Zampini -  max_levels - the maximum number of levels
2054fad6a16SStefano Zampini 
2064fad6a16SStefano Zampini    Default value is 1, i.e. coarse problem will be solved inexactly with one application
2074fad6a16SStefano Zampini    of PCBDDC preconditioner if the multilevel approach is requested.
2084fad6a16SStefano Zampini 
2094fad6a16SStefano Zampini    Level: intermediate
2104fad6a16SStefano Zampini 
2114fad6a16SStefano Zampini    Notes:
2124fad6a16SStefano Zampini 
2134fad6a16SStefano Zampini .seealso: PCBDDC
2144fad6a16SStefano Zampini @*/
2154fad6a16SStefano Zampini PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
2164fad6a16SStefano Zampini {
2174fad6a16SStefano Zampini   PetscErrorCode ierr;
2184fad6a16SStefano Zampini 
2194fad6a16SStefano Zampini   PetscFunctionBegin;
2204fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2214fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
2224fad6a16SStefano Zampini   PetscFunctionReturn(0);
2234fad6a16SStefano Zampini }
2244fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
2251e6b0712SBarry Smith 
2264fad6a16SStefano Zampini #undef __FUNCT__
2270bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
2280bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
2290bdf917eSStefano Zampini {
2300bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2310bdf917eSStefano Zampini   PetscErrorCode ierr;
2320bdf917eSStefano Zampini 
2330bdf917eSStefano Zampini   PetscFunctionBegin;
2340bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
2350bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
2360bdf917eSStefano Zampini   pcbddc->NullSpace=NullSpace;
2370bdf917eSStefano Zampini   PetscFunctionReturn(0);
2380bdf917eSStefano Zampini }
2391e6b0712SBarry Smith 
2400bdf917eSStefano Zampini #undef __FUNCT__
2410bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
2420bdf917eSStefano Zampini /*@
2430bdf917eSStefano Zampini  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
2440bdf917eSStefano Zampini 
2450bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
2460bdf917eSStefano Zampini 
2470bdf917eSStefano Zampini    Input Parameters:
2480bdf917eSStefano Zampini +  pc - the preconditioning context
2490bdf917eSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned.
2500bdf917eSStefano Zampini 
2510bdf917eSStefano Zampini    Level: intermediate
2520bdf917eSStefano Zampini 
2530bdf917eSStefano Zampini    Notes:
2540bdf917eSStefano Zampini 
2550bdf917eSStefano Zampini .seealso: PCBDDC
2560bdf917eSStefano Zampini @*/
2570bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
2580bdf917eSStefano Zampini {
2590bdf917eSStefano Zampini   PetscErrorCode ierr;
2600bdf917eSStefano Zampini 
2610bdf917eSStefano Zampini   PetscFunctionBegin;
2620bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
263674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
2640bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
2650bdf917eSStefano Zampini   PetscFunctionReturn(0);
2660bdf917eSStefano Zampini }
2670bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
2681e6b0712SBarry Smith 
2690bdf917eSStefano Zampini #undef __FUNCT__
2703b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
2713b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
2723b03a366Sstefano_zampini {
2733b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2743b03a366Sstefano_zampini   PetscErrorCode ierr;
2753b03a366Sstefano_zampini 
2763b03a366Sstefano_zampini   PetscFunctionBegin;
2773b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
27836e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
27936e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
2803b03a366Sstefano_zampini   PetscFunctionReturn(0);
2813b03a366Sstefano_zampini }
2821e6b0712SBarry Smith 
2833b03a366Sstefano_zampini #undef __FUNCT__
2843b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
2853b03a366Sstefano_zampini /*@
286da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
287da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
2883b03a366Sstefano_zampini 
2893b03a366Sstefano_zampini    Not collective
2903b03a366Sstefano_zampini 
2913b03a366Sstefano_zampini    Input Parameters:
2923b03a366Sstefano_zampini +  pc - the preconditioning context
2930298fd71SBarry Smith -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL)
2943b03a366Sstefano_zampini 
2953b03a366Sstefano_zampini    Level: intermediate
2963b03a366Sstefano_zampini 
2973b03a366Sstefano_zampini    Notes:
2983b03a366Sstefano_zampini 
2993b03a366Sstefano_zampini .seealso: PCBDDC
3003b03a366Sstefano_zampini @*/
3013b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
3023b03a366Sstefano_zampini {
3033b03a366Sstefano_zampini   PetscErrorCode ierr;
3043b03a366Sstefano_zampini 
3053b03a366Sstefano_zampini   PetscFunctionBegin;
3063b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
307674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
3083b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
3093b03a366Sstefano_zampini   PetscFunctionReturn(0);
3103b03a366Sstefano_zampini }
3113b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
3121e6b0712SBarry Smith 
3133b03a366Sstefano_zampini #undef __FUNCT__
3140c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
31553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
3160c7d97c5SJed Brown {
3170c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
31853cdbc3dSStefano Zampini   PetscErrorCode ierr;
3190c7d97c5SJed Brown 
3200c7d97c5SJed Brown   PetscFunctionBegin;
32153cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
32236e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
32336e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
3240c7d97c5SJed Brown   PetscFunctionReturn(0);
3250c7d97c5SJed Brown }
3261e6b0712SBarry Smith 
3270c7d97c5SJed Brown #undef __FUNCT__
3280c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
32957527edcSJed Brown /*@
330da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
331da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
33257527edcSJed Brown 
3339c0446d6SStefano Zampini    Not collective
33457527edcSJed Brown 
33557527edcSJed Brown    Input Parameters:
33657527edcSJed Brown +  pc - the preconditioning context
3370298fd71SBarry Smith -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL)
33857527edcSJed Brown 
33957527edcSJed Brown    Level: intermediate
34057527edcSJed Brown 
34157527edcSJed Brown    Notes:
34257527edcSJed Brown 
34357527edcSJed Brown .seealso: PCBDDC
34457527edcSJed Brown @*/
34553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
3460c7d97c5SJed Brown {
3470c7d97c5SJed Brown   PetscErrorCode ierr;
3480c7d97c5SJed Brown 
3490c7d97c5SJed Brown   PetscFunctionBegin;
3500c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
351674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
35253cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
35353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
35453cdbc3dSStefano Zampini }
35553cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
3561e6b0712SBarry Smith 
35753cdbc3dSStefano Zampini #undef __FUNCT__
358da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
359da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
360da1bb401SStefano Zampini {
361da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
362da1bb401SStefano Zampini 
363da1bb401SStefano Zampini   PetscFunctionBegin;
364da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
365da1bb401SStefano Zampini   PetscFunctionReturn(0);
366da1bb401SStefano Zampini }
3671e6b0712SBarry Smith 
368da1bb401SStefano Zampini #undef __FUNCT__
369da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
370da1bb401SStefano Zampini /*@
371da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
372da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
373da1bb401SStefano Zampini 
374da1bb401SStefano Zampini    Not collective
375da1bb401SStefano Zampini 
376da1bb401SStefano Zampini    Input Parameters:
377da1bb401SStefano Zampini +  pc - the preconditioning context
378da1bb401SStefano Zampini 
379da1bb401SStefano Zampini    Output Parameters:
380da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
381da1bb401SStefano Zampini 
382da1bb401SStefano Zampini    Level: intermediate
383da1bb401SStefano Zampini 
384da1bb401SStefano Zampini    Notes:
385da1bb401SStefano Zampini 
386da1bb401SStefano Zampini .seealso: PCBDDC
387da1bb401SStefano Zampini @*/
388da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
389da1bb401SStefano Zampini {
390da1bb401SStefano Zampini   PetscErrorCode ierr;
391da1bb401SStefano Zampini 
392da1bb401SStefano Zampini   PetscFunctionBegin;
393da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
394da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
395da1bb401SStefano Zampini   PetscFunctionReturn(0);
396da1bb401SStefano Zampini }
397da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
3981e6b0712SBarry Smith 
399da1bb401SStefano Zampini #undef __FUNCT__
40053cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
40153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
40253cdbc3dSStefano Zampini {
40353cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
40453cdbc3dSStefano Zampini 
40553cdbc3dSStefano Zampini   PetscFunctionBegin;
40653cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
40753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
40853cdbc3dSStefano Zampini }
4091e6b0712SBarry Smith 
41053cdbc3dSStefano Zampini #undef __FUNCT__
41153cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
41253cdbc3dSStefano Zampini /*@
413da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
414da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
41553cdbc3dSStefano Zampini 
4169c0446d6SStefano Zampini    Not collective
41753cdbc3dSStefano Zampini 
41853cdbc3dSStefano Zampini    Input Parameters:
41953cdbc3dSStefano Zampini +  pc - the preconditioning context
42053cdbc3dSStefano Zampini 
42153cdbc3dSStefano Zampini    Output Parameters:
42253cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
42353cdbc3dSStefano Zampini 
42453cdbc3dSStefano Zampini    Level: intermediate
42553cdbc3dSStefano Zampini 
42653cdbc3dSStefano Zampini    Notes:
42753cdbc3dSStefano Zampini 
42853cdbc3dSStefano Zampini .seealso: PCBDDC
42953cdbc3dSStefano Zampini @*/
43053cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
43153cdbc3dSStefano Zampini {
43253cdbc3dSStefano Zampini   PetscErrorCode ierr;
43353cdbc3dSStefano Zampini 
43453cdbc3dSStefano Zampini   PetscFunctionBegin;
43553cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43653cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
4370c7d97c5SJed Brown   PetscFunctionReturn(0);
4380c7d97c5SJed Brown }
43936e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
4401e6b0712SBarry Smith 
44136e030ebSStefano Zampini #undef __FUNCT__
442da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
4431a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
44436e030ebSStefano Zampini {
44536e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
446da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
447da1bb401SStefano Zampini   PetscErrorCode ierr;
44836e030ebSStefano Zampini 
44936e030ebSStefano Zampini   PetscFunctionBegin;
450674ae819SStefano Zampini   /* free old CSR */
451674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
452fb223d50SStefano Zampini   /* TODO: PCBDDCGraphSetAdjacency */
453674ae819SStefano Zampini   /* get CSR into graph structure */
454da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
455674ae819SStefano Zampini     ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
456674ae819SStefano Zampini     ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
457674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
458674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
459da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4601a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4611a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
462674ae819SStefano Zampini   }
463575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
46436e030ebSStefano Zampini   PetscFunctionReturn(0);
46536e030ebSStefano Zampini }
4661e6b0712SBarry Smith 
46736e030ebSStefano Zampini #undef __FUNCT__
468da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
46936e030ebSStefano Zampini /*@
470da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
47136e030ebSStefano Zampini 
47236e030ebSStefano Zampini    Not collective
47336e030ebSStefano Zampini 
47436e030ebSStefano Zampini    Input Parameters:
47536e030ebSStefano Zampini +  pc - the preconditioning context
476da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
477da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
478da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
479da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
48036e030ebSStefano Zampini 
48136e030ebSStefano Zampini    Level: intermediate
48236e030ebSStefano Zampini 
48336e030ebSStefano Zampini    Notes:
48436e030ebSStefano Zampini 
48536e030ebSStefano Zampini .seealso: PCBDDC
48636e030ebSStefano Zampini @*/
4871a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
48836e030ebSStefano Zampini {
489575ad6abSStefano Zampini   void (*f)(void) = 0;
49036e030ebSStefano Zampini   PetscErrorCode ierr;
49136e030ebSStefano Zampini 
49236e030ebSStefano Zampini   PetscFunctionBegin;
49336e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
494674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
495674ae819SStefano Zampini   PetscValidIntPointer(xadj,4);
496674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
497674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
498da1bb401SStefano Zampini   }
49936e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
500575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
501575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
502575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
503575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
504575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
50536e030ebSStefano Zampini   }
50636e030ebSStefano Zampini   PetscFunctionReturn(0);
50736e030ebSStefano Zampini }
5089c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
5091e6b0712SBarry Smith 
5109c0446d6SStefano Zampini #undef __FUNCT__
5119c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
5129c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
5139c0446d6SStefano Zampini {
5149c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5159c0446d6SStefano Zampini   PetscInt i;
5169c0446d6SStefano Zampini   PetscErrorCode ierr;
5179c0446d6SStefano Zampini 
5189c0446d6SStefano Zampini   PetscFunctionBegin;
519da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
5209c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
5219c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
5229c0446d6SStefano Zampini   }
523d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
524da1bb401SStefano Zampini   /* allocate space then set */
5259c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
5269c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
527da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
528da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
5299c0446d6SStefano Zampini   }
5309c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
5319c0446d6SStefano Zampini   PetscFunctionReturn(0);
5329c0446d6SStefano Zampini }
5331e6b0712SBarry Smith 
5349c0446d6SStefano Zampini #undef __FUNCT__
5359c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
5369c0446d6SStefano Zampini /*@
537da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
5389c0446d6SStefano Zampini 
5399c0446d6SStefano Zampini    Not collective
5409c0446d6SStefano Zampini 
5419c0446d6SStefano Zampini    Input Parameters:
5429c0446d6SStefano Zampini +  pc - the preconditioning context
543da1bb401SStefano Zampini -  n - number of index sets defining the fields
544da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
5459c0446d6SStefano Zampini 
5469c0446d6SStefano Zampini    Level: intermediate
5479c0446d6SStefano Zampini 
5489c0446d6SStefano Zampini    Notes:
5499c0446d6SStefano Zampini 
5509c0446d6SStefano Zampini .seealso: PCBDDC
5519c0446d6SStefano Zampini @*/
5529c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
5539c0446d6SStefano Zampini {
5549c0446d6SStefano Zampini   PetscErrorCode ierr;
5559c0446d6SStefano Zampini 
5569c0446d6SStefano Zampini   PetscFunctionBegin;
5579c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5589c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5599c0446d6SStefano Zampini   PetscFunctionReturn(0);
5609c0446d6SStefano Zampini }
561da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
562534831adSStefano Zampini #undef __FUNCT__
563534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
564534831adSStefano Zampini /* -------------------------------------------------------------------------- */
565534831adSStefano Zampini /*
566534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
567534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5689c0446d6SStefano Zampini 
569534831adSStefano Zampini    Input Parameter:
570534831adSStefano Zampini +  pc - the preconditioner contex
571534831adSStefano Zampini 
572534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
573534831adSStefano Zampini 
574534831adSStefano Zampini    Notes:
575534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
576534831adSStefano Zampini    the user, but instead is called by KSPSolve().
577534831adSStefano Zampini */
578534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
579534831adSStefano Zampini {
580534831adSStefano Zampini   PetscErrorCode ierr;
581534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
582534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
583534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
584534831adSStefano Zampini   Mat            temp_mat;
5853972b0daSStefano Zampini   IS             dirIS;
5863972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5873972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5883972b0daSStefano Zampini   Vec            used_vec;
5893972b0daSStefano Zampini   PetscBool      guess_nonzero;
590534831adSStefano Zampini 
591534831adSStefano Zampini   PetscFunctionBegin;
59262a6ff1dSStefano Zampini   /* Creates parallel work vectors used in presolve. */
59362a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
59462a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
59562a6ff1dSStefano Zampini   }
59662a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
59762a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
59862a6ff1dSStefano Zampini   }
5993972b0daSStefano Zampini   if (x) {
6003972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
6013972b0daSStefano Zampini     used_vec = x;
6023972b0daSStefano Zampini   } else {
6033972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
6043972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
6053972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6063972b0daSStefano Zampini   }
6073972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
6083972b0daSStefano Zampini   if (ksp) {
6093972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
6103972b0daSStefano Zampini     if ( !guess_nonzero ) {
6113972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
6123972b0daSStefano Zampini     }
6133972b0daSStefano Zampini   }
6143308cffdSStefano Zampini 
61562a6ff1dSStefano Zampini   if (rhs) { /* TODO: wiser handling of rhs removal, which is only needed in case of zeroed rows */
6163972b0daSStefano Zampini     /* store the original rhs */
6173972b0daSStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
6183972b0daSStefano Zampini 
6193972b0daSStefano Zampini     /* Take into account zeroed rows -> change rhs and store solution removed */
6203972b0daSStefano Zampini     ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
6213972b0daSStefano Zampini     ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
6223972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6233972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6243972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6253972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6263972b0daSStefano Zampini     ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
6273972b0daSStefano Zampini     if (dirIS) {
6283972b0daSStefano Zampini       ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
6293972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6303972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6313972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6322fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
6333972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
6343972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
6353972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
6363972b0daSStefano Zampini     }
6373972b0daSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6383972b0daSStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
639b76ba322SStefano Zampini 
6403972b0daSStefano Zampini     /* remove the computed solution from the rhs */
6413972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6423972b0daSStefano Zampini     ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
6433972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
6443308cffdSStefano Zampini   }
645b76ba322SStefano Zampini 
646b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
6473972b0daSStefano Zampini   if (x) {
6483972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
6493972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
65015aaf578SStefano Zampini     if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) {
651b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
652b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
653b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
654b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
655b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
656b76ba322SStefano Zampini       if (ksp) {
657b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
658b76ba322SStefano Zampini       }
659b76ba322SStefano Zampini     }
6603972b0daSStefano Zampini   }
661b76ba322SStefano Zampini 
662674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
663b76ba322SStefano Zampini     /* swap pointers for local matrices */
664b76ba322SStefano Zampini     temp_mat = matis->A;
665b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
666b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
6673308cffdSStefano Zampini   }
6683308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && rhs) {
669b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
670b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
671b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
672b76ba322SStefano Zampini     /* from original basis to modified basis */
673b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
674b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
675b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
676b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
677674ae819SStefano Zampini   }
6780bdf917eSStefano Zampini   if (ksp && pcbddc->NullSpace) {
679d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr);
680d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
681b76ba322SStefano Zampini   }
6820bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
683534831adSStefano Zampini   PetscFunctionReturn(0);
684534831adSStefano Zampini }
685534831adSStefano Zampini /* -------------------------------------------------------------------------- */
686534831adSStefano Zampini #undef __FUNCT__
687534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
688534831adSStefano Zampini /* -------------------------------------------------------------------------- */
689534831adSStefano Zampini /*
690534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
691534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
692534831adSStefano Zampini 
693534831adSStefano Zampini    Input Parameter:
694534831adSStefano Zampini +  pc - the preconditioner contex
695534831adSStefano Zampini 
696534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
697534831adSStefano Zampini 
698534831adSStefano Zampini    Notes:
699534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
700534831adSStefano Zampini    the user, but instead is called by KSPSolve().
701534831adSStefano Zampini */
702534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
703534831adSStefano Zampini {
704534831adSStefano Zampini   PetscErrorCode ierr;
705534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
706534831adSStefano Zampini   PC_IS          *pcis   = (PC_IS*)(pc->data);
707534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
708534831adSStefano Zampini   Mat            temp_mat;
709534831adSStefano Zampini 
710534831adSStefano Zampini   PetscFunctionBegin;
711674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
712534831adSStefano Zampini     /* swap pointers for local matrices */
713534831adSStefano Zampini     temp_mat = matis->A;
714534831adSStefano Zampini     matis->A = pcbddc->local_mat;
715534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
7163425bc38SStefano Zampini   }
7173308cffdSStefano Zampini   if (pcbddc->use_change_of_basis && x) {
718534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
719534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
720534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
721534831adSStefano Zampini     /* from modified basis to original basis */
722534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
723534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
724534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
725534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
726534831adSStefano Zampini   }
7273972b0daSStefano Zampini   /* add solution removed in presolve */
7283425bc38SStefano Zampini   if (x) {
7293425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
7303425bc38SStefano Zampini   }
731fb223d50SStefano Zampini   /* restore rhs to its original state */
732fb223d50SStefano Zampini   if (rhs) {
733fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
734fb223d50SStefano Zampini   }
735534831adSStefano Zampini   PetscFunctionReturn(0);
736534831adSStefano Zampini }
737534831adSStefano Zampini /* -------------------------------------------------------------------------- */
73853cdbc3dSStefano Zampini #undef __FUNCT__
73953cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
7400c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7410c7d97c5SJed Brown /*
7420c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
7430c7d97c5SJed Brown                   by setting data structures and options.
7440c7d97c5SJed Brown 
7450c7d97c5SJed Brown    Input Parameter:
74653cdbc3dSStefano Zampini +  pc - the preconditioner context
7470c7d97c5SJed Brown 
7480c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
7490c7d97c5SJed Brown 
7500c7d97c5SJed Brown    Notes:
7510c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
7520c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
7530c7d97c5SJed Brown */
75453cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
7550c7d97c5SJed Brown {
7560c7d97c5SJed Brown   PetscErrorCode ierr;
7570c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
758674ae819SStefano Zampini   MatStructure   flag;
759674ae819SStefano Zampini   PetscBool      computeis,computetopography,computesolvers;
7600c7d97c5SJed Brown 
7610c7d97c5SJed Brown   PetscFunctionBegin;
762674ae819SStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */
7633b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
7649c0446d6SStefano Zampini      So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
7650c7d97c5SJed Brown      Also, we decide to directly build the (same) Dirichlet problem */
7660c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
7670c7d97c5SJed Brown   ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
7683b03a366Sstefano_zampini   /* Get stdout for dbg */
769674ae819SStefano Zampini   if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) {
770ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr);
771e269702eSStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
772e269702eSStefano Zampini   }
773674ae819SStefano Zampini   /* first attempt to split work */
774674ae819SStefano Zampini   if (pc->setupcalled) {
775674ae819SStefano Zampini     computeis = PETSC_FALSE;
776674ae819SStefano Zampini     ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr);
777674ae819SStefano Zampini     if (flag == SAME_PRECONDITIONER) {
778674ae819SStefano Zampini       computetopography = PETSC_FALSE;
779674ae819SStefano Zampini       computesolvers = PETSC_FALSE;
780674ae819SStefano Zampini     } else if (flag == SAME_NONZERO_PATTERN) {
781674ae819SStefano Zampini       computetopography = PETSC_FALSE;
782674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
783674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
784674ae819SStefano Zampini       computetopography = PETSC_TRUE;
785674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
786674ae819SStefano Zampini     }
787674ae819SStefano Zampini   } else {
788674ae819SStefano Zampini     computeis = PETSC_TRUE;
789674ae819SStefano Zampini     computetopography = PETSC_TRUE;
790674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
791674ae819SStefano Zampini   }
792674ae819SStefano Zampini   /* Set up all the "iterative substructuring" common block */
793674ae819SStefano Zampini   if (computeis) {
794674ae819SStefano Zampini     ierr = PCISSetUp(pc);CHKERRQ(ierr);
795674ae819SStefano Zampini   }
796674ae819SStefano Zampini   /* Analyze interface and set up local constraint and change of basis matrices */
797674ae819SStefano Zampini   if (computetopography) {
798674ae819SStefano Zampini     /* reset data */
799674ae819SStefano Zampini     ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
800674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
801674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
802674ae819SStefano Zampini   }
803674ae819SStefano Zampini   if (computesolvers) {
804674ae819SStefano Zampini     /* reset data */
805674ae819SStefano Zampini     ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
806674ae819SStefano Zampini     ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
807*99cc7994SStefano Zampini     /* Create coarse and local stuffs */
808*99cc7994SStefano Zampini     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
809674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
8100c7d97c5SJed Brown   }
8110c7d97c5SJed Brown   PetscFunctionReturn(0);
8120c7d97c5SJed Brown }
8130c7d97c5SJed Brown 
8140c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
8150c7d97c5SJed Brown /*
8160c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
8170c7d97c5SJed Brown 
8180c7d97c5SJed Brown    Input Parameters:
8190c7d97c5SJed Brown .  pc - the preconditioner context
8200c7d97c5SJed Brown .  r - input vector (global)
8210c7d97c5SJed Brown 
8220c7d97c5SJed Brown    Output Parameter:
8230c7d97c5SJed Brown .  z - output vector (global)
8240c7d97c5SJed Brown 
8250c7d97c5SJed Brown    Application Interface Routine: PCApply()
8260c7d97c5SJed Brown  */
8270c7d97c5SJed Brown #undef __FUNCT__
8280c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
82953cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
8300c7d97c5SJed Brown {
8310c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
8320c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
8330c7d97c5SJed Brown   PetscErrorCode    ierr;
8343b03a366Sstefano_zampini   const PetscScalar one = 1.0;
8353b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
8362617d88aSStefano Zampini   const PetscScalar zero = 0.0;
8370c7d97c5SJed Brown 
8380c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
8390c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
84029622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
8410c7d97c5SJed Brown 
8420c7d97c5SJed Brown   PetscFunctionBegin;
84315aaf578SStefano Zampini   if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) {
8440c7d97c5SJed Brown     /* First Dirichlet solve */
8450c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8460c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
84753cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
8480c7d97c5SJed Brown     /*
8490c7d97c5SJed Brown       Assembling right hand side for BDDC operator
850674ae819SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
851674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
8520c7d97c5SJed Brown     */
8530c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8540c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
85529622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
8560c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
8570c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
8580c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8590c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
860674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
861b76ba322SStefano Zampini   } else {
8620bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
863b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
864674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
865b76ba322SStefano Zampini   }
866b76ba322SStefano Zampini 
8672617d88aSStefano Zampini   /* Apply interface preconditioner
8682617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
8692617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
8702617d88aSStefano Zampini 
871674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
872674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
8730c7d97c5SJed Brown 
8743b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
8750c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8760c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8770c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
87829622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
87953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
8800c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
88129622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
8820c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
8830c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8840c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8850c7d97c5SJed Brown   PetscFunctionReturn(0);
8860c7d97c5SJed Brown }
887da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
888674ae819SStefano Zampini 
889da1bb401SStefano Zampini #undef __FUNCT__
890da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
891da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
892da1bb401SStefano Zampini {
893da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
894da1bb401SStefano Zampini   PetscErrorCode ierr;
895da1bb401SStefano Zampini 
896da1bb401SStefano Zampini   PetscFunctionBegin;
897da1bb401SStefano Zampini   /* free data created by PCIS */
898da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
899674ae819SStefano Zampini   /* free BDDC custom data  */
900674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
901674ae819SStefano Zampini   /* destroy objects related to topography */
902674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
903674ae819SStefano Zampini   /* free allocated graph structure */
904da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
905674ae819SStefano Zampini   /* free data for scaling operator */
906674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
907674ae819SStefano Zampini   /* free solvers stuff */
908674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
90933bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
91033bc96a4SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
911ac78edfcSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
91262a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
91362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
91462a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
9153425bc38SStefano Zampini   /* remove functions */
916674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
917bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
918bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",NULL);CHKERRQ(ierr);
919bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
920bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
921bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
922bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
923bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
924bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",NULL);CHKERRQ(ierr);
925bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
926bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
927bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
928bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
929bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
930674ae819SStefano Zampini   /* Free the private data structure */
931674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
932da1bb401SStefano Zampini   PetscFunctionReturn(0);
933da1bb401SStefano Zampini }
9343425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9351e6b0712SBarry Smith 
9363425bc38SStefano Zampini #undef __FUNCT__
9373425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
9383425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9393425bc38SStefano Zampini {
940674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
9413425bc38SStefano Zampini   PC_IS*         pcis;
9423425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9433425bc38SStefano Zampini   PetscErrorCode ierr;
9440c7d97c5SJed Brown 
9453425bc38SStefano Zampini   PetscFunctionBegin;
9463425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9473425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9483425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9493425bc38SStefano Zampini 
9503425bc38SStefano Zampini   /* change of basis for physical rhs if needed
9513425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
9523308cffdSStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr);
9533425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9543425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9553425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
956fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
957fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
9583425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9593425bc38SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
960674ae819SStefano Zampini   /* Apply partition of unity */
9613425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
962674ae819SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
96329622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9643425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9653425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9663425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9673425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9683425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9693425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9703425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
971674ae819SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
9723425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9733425bc38SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9743425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9753425bc38SStefano Zampini   }
9763425bc38SStefano Zampini   /* BDDC rhs */
9773425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
97829622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9793425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9803425bc38SStefano Zampini   }
9813425bc38SStefano Zampini   /* apply BDDC */
9823425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9833425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9843425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9853425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9863425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9873425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9883425bc38SStefano Zampini   /* restore original rhs */
9893425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9903425bc38SStefano Zampini   PetscFunctionReturn(0);
9913425bc38SStefano Zampini }
9921e6b0712SBarry Smith 
9933425bc38SStefano Zampini #undef __FUNCT__
9943425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9953425bc38SStefano Zampini /*@
9963425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9973425bc38SStefano Zampini 
9983425bc38SStefano Zampini    Collective
9993425bc38SStefano Zampini 
10003425bc38SStefano Zampini    Input Parameters:
10013425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10023425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
10033425bc38SStefano Zampini 
10043425bc38SStefano Zampini    Output Parameters:
10053425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
10063425bc38SStefano Zampini 
10073425bc38SStefano Zampini    Level: developer
10083425bc38SStefano Zampini 
10093425bc38SStefano Zampini    Notes:
10103425bc38SStefano Zampini 
10113425bc38SStefano Zampini .seealso: PCBDDC
10123425bc38SStefano Zampini @*/
10133425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
10143425bc38SStefano Zampini {
1015674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10163425bc38SStefano Zampini   PetscErrorCode ierr;
10173425bc38SStefano Zampini 
10183425bc38SStefano Zampini   PetscFunctionBegin;
10193425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10203425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
10213425bc38SStefano Zampini   PetscFunctionReturn(0);
10223425bc38SStefano Zampini }
10233425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10241e6b0712SBarry Smith 
10253425bc38SStefano Zampini #undef __FUNCT__
10263425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
10273425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10283425bc38SStefano Zampini {
1029674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10303425bc38SStefano Zampini   PC_IS*         pcis;
10313425bc38SStefano Zampini   PC_BDDC*       pcbddc;
10323425bc38SStefano Zampini   PetscErrorCode ierr;
10333425bc38SStefano Zampini 
10343425bc38SStefano Zampini   PetscFunctionBegin;
10353425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10363425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
10373425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
10383425bc38SStefano Zampini 
10393425bc38SStefano Zampini   /* apply B_delta^T */
10403425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10413425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10423425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
10433425bc38SStefano Zampini   /* compute rhs for BDDC application */
10443425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
104529622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
10463425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10473425bc38SStefano Zampini   }
10483425bc38SStefano Zampini   /* apply BDDC */
10493425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
10503425bc38SStefano Zampini   /* put values into standard global vector */
10513425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10523425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
105329622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
10543425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
10553425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
10563425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
10573425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10583425bc38SStefano Zampini   }
10593425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10603425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10613425bc38SStefano Zampini   /* final change of basis if needed
10623425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10633308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
10643425bc38SStefano Zampini   PetscFunctionReturn(0);
10653425bc38SStefano Zampini }
10661e6b0712SBarry Smith 
10673425bc38SStefano Zampini #undef __FUNCT__
10683425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10693425bc38SStefano Zampini /*@
10703425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10713425bc38SStefano Zampini 
10723425bc38SStefano Zampini    Collective
10733425bc38SStefano Zampini 
10743425bc38SStefano Zampini    Input Parameters:
10753425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10763425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10773425bc38SStefano Zampini 
10783425bc38SStefano Zampini    Output Parameters:
10793425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10803425bc38SStefano Zampini 
10813425bc38SStefano Zampini    Level: developer
10823425bc38SStefano Zampini 
10833425bc38SStefano Zampini    Notes:
10843425bc38SStefano Zampini 
10853425bc38SStefano Zampini .seealso: PCBDDC
10863425bc38SStefano Zampini @*/
10873425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10883425bc38SStefano Zampini {
1089674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
10903425bc38SStefano Zampini   PetscErrorCode ierr;
10913425bc38SStefano Zampini 
10923425bc38SStefano Zampini   PetscFunctionBegin;
10933425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10943425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10953425bc38SStefano Zampini   PetscFunctionReturn(0);
10963425bc38SStefano Zampini }
10973425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10981e6b0712SBarry Smith 
1099f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1100f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1101f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1102f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
1103674ae819SStefano Zampini 
11043425bc38SStefano Zampini #undef __FUNCT__
11053425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
11063425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11073425bc38SStefano Zampini {
1108674ae819SStefano Zampini 
1109674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
11103425bc38SStefano Zampini   Mat            newmat;
1111674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
11123425bc38SStefano Zampini   PC             newpc;
1113ce94432eSBarry Smith   MPI_Comm       comm;
11143425bc38SStefano Zampini   PetscErrorCode ierr;
11153425bc38SStefano Zampini 
11163425bc38SStefano Zampini   PetscFunctionBegin;
1117ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
11183425bc38SStefano Zampini   /* FETIDP linear matrix */
11193425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
11203425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
11213425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
11223425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
11233425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
11243425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
11253425bc38SStefano Zampini   /* FETIDP preconditioner */
11263425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
11273425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
11283425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
11293425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
11303425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
11313425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
11323425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
11333425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
11343425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
11353425bc38SStefano Zampini   /* return pointers for objects created */
11363425bc38SStefano Zampini   *fetidp_mat=newmat;
11373425bc38SStefano Zampini   *fetidp_pc=newpc;
11383425bc38SStefano Zampini   PetscFunctionReturn(0);
11393425bc38SStefano Zampini }
11401e6b0712SBarry Smith 
11413425bc38SStefano Zampini #undef __FUNCT__
11423425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
11433425bc38SStefano Zampini /*@
11443425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
11453425bc38SStefano Zampini 
11463425bc38SStefano Zampini    Collective
11473425bc38SStefano Zampini 
11483425bc38SStefano Zampini    Input Parameters:
11493425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
11503425bc38SStefano Zampini 
11513425bc38SStefano Zampini    Level: developer
11523425bc38SStefano Zampini 
11533425bc38SStefano Zampini    Notes:
11543425bc38SStefano Zampini 
11553425bc38SStefano Zampini .seealso: PCBDDC
11563425bc38SStefano Zampini @*/
11573425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
11583425bc38SStefano Zampini {
11593425bc38SStefano Zampini   PetscErrorCode ierr;
11603425bc38SStefano Zampini 
11613425bc38SStefano Zampini   PetscFunctionBegin;
11623425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11633425bc38SStefano Zampini   if (pc->setupcalled) {
11643425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1165f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11663425bc38SStefano Zampini   PetscFunctionReturn(0);
11673425bc38SStefano Zampini }
11680c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1169da1bb401SStefano Zampini /*MC
1170da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11710c7d97c5SJed Brown 
1172da1bb401SStefano Zampini    Options Database Keys:
1173da1bb401SStefano Zampini .    -pcbddc ??? -
1174da1bb401SStefano Zampini 
1175da1bb401SStefano Zampini    Level: intermediate
1176da1bb401SStefano Zampini 
1177da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1178da1bb401SStefano Zampini 
1179da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1180da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1181da1bb401SStefano Zampini           on the subdomains).
1182da1bb401SStefano Zampini 
1183da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1184da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1185da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1186da1bb401SStefano Zampini 
1187da1bb401SStefano Zampini    Contributed by Stefano Zampini
1188da1bb401SStefano Zampini 
1189da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1190da1bb401SStefano Zampini M*/
1191b2573a8aSBarry Smith 
1192da1bb401SStefano Zampini #undef __FUNCT__
1193da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
11948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
1195da1bb401SStefano Zampini {
1196da1bb401SStefano Zampini   PetscErrorCode      ierr;
1197da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
1198da1bb401SStefano Zampini 
1199da1bb401SStefano Zampini   PetscFunctionBegin;
1200da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1201da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1202da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1203da1bb401SStefano Zampini 
1204da1bb401SStefano Zampini   /* create PCIS data structure */
1205da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1206da1bb401SStefano Zampini 
1207da1bb401SStefano Zampini   /* BDDC specific */
1208674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
12090bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
12103972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1211534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1212534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1213534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1214674ae819SStefano Zampini   pcbddc->use_change_of_basis        = PETSC_TRUE;
1215674ae819SStefano Zampini   pcbddc->use_change_on_faces        = PETSC_FALSE;
1216da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1217da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1218da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1219da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1220da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
122115aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
122215aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
1223da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1224da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1225da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1226da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1227da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1228da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1229da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1230da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1231da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1232da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
123329622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1234da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1235da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1236da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1237da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1238da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1239da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1240da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
12419d9e44b6SStefano Zampini   pcbddc->dbg_flag                   = 0;
1242da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1243b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
12444fad6a16SStefano Zampini   pcbddc->current_level              = 0;
12454fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1246674ae819SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1247674ae819SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1248da1bb401SStefano Zampini 
1249674ae819SStefano Zampini   /* create local graph structure */
1250674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
1251674ae819SStefano Zampini 
1252674ae819SStefano Zampini   /* scaling */
1253674ae819SStefano Zampini   pcbddc->use_deluxe_scaling         = PETSC_FALSE;
1254674ae819SStefano Zampini   pcbddc->work_scaling               = 0;
1255da1bb401SStefano Zampini 
1256da1bb401SStefano Zampini   /* function pointers */
1257da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1258da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1259da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1260da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1261da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1262da1bb401SStefano Zampini   pc->ops->view                = 0;
1263da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1264da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1265da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1266534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1267534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1268da1bb401SStefano Zampini 
1269da1bb401SStefano Zampini   /* composing function */
1270674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
1271bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
1272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetMaxLevels_C",PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
1273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1274bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1275bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1276bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1277bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1278bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseProblemType_C",PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1279bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1280bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1281bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
1282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
1283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1284da1bb401SStefano Zampini   PetscFunctionReturn(0);
1285da1bb401SStefano Zampini }
12863425bc38SStefano Zampini 
1287da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1288da1bb401SStefano Zampini /* All static functions from now on                                           */
1289da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
129029622bf0SStefano Zampini 
12913b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
12920c7d97c5SJed Brown #undef __FUNCT__
1293*99cc7994SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1294*99cc7994SStefano Zampini static PetscErrorCode PCBDDCSetUpSolvers(PC pc)
12950c7d97c5SJed Brown {
12960c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1297dcedc2aeSStefano Zampini   PetscErrorCode    ierr;
1298dcedc2aeSStefano Zampini 
1299dcedc2aeSStefano Zampini   PetscFunctionBegin;
1300*99cc7994SStefano Zampini   /* Compute matrix after change of basis and extract local submatrices */
1301dcedc2aeSStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
1302dcedc2aeSStefano Zampini 
1303*99cc7994SStefano Zampini   /* Allocate needed vectors */
1304*99cc7994SStefano Zampini   ierr = PCBDDCCreateWorkVectors(pc);CHKERRQ(ierr);
1305*99cc7994SStefano Zampini 
1306*99cc7994SStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D : PCBDDCCreateWorkVectors should be called first! */
1307*99cc7994SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1308*99cc7994SStefano Zampini 
1309*99cc7994SStefano Zampini   /* Setup local solvers ksp_D and ksp_R */
1310*99cc7994SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc);CHKERRQ(ierr);
1311*99cc7994SStefano Zampini 
1312dcedc2aeSStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
1313dcedc2aeSStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
1314dcedc2aeSStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
1315dcedc2aeSStefano Zampini   }
1316dcedc2aeSStefano Zampini 
131788ebb749SStefano Zampini   /* setup local correction and local part of coarse basis */
13188ce42a96SStefano Zampini   ierr = PCBDDCSetUpCoarseLocal(pc);CHKERRQ(ierr);
1319674ae819SStefano Zampini 
13200c7d97c5SJed Brown   PetscFunctionReturn(0);
13210c7d97c5SJed Brown }
13220c7d97c5SJed Brown 
13230c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13240c7d97c5SJed Brown 
13257cbb387bSStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
13267cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
13277cbb387bSStefano Zampini #include "metis.h"
13287cbb387bSStefano Zampini #define MetisInt    idx_t
13297cbb387bSStefano Zampini #define MetisScalar real_t
13307cbb387bSStefano Zampini #endif
13317cbb387bSStefano Zampini 
13320c7d97c5SJed Brown #undef __FUNCT__
1333674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseEnvironment"
133488ebb749SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
13350c7d97c5SJed Brown {
1336674ae819SStefano Zampini 
1337674ae819SStefano Zampini 
13380c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
13390c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
13400c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1341ce94432eSBarry Smith   MPI_Comm  prec_comm;
13420c7d97c5SJed Brown   MPI_Comm  coarse_comm;
13430c7d97c5SJed Brown 
1344674ae819SStefano Zampini   MatNullSpace CoarseNullSpace;
1345674ae819SStefano Zampini 
13460c7d97c5SJed Brown   /* common to all choiches */
13470c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
13480c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
13490c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
13500c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
13510c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
13520c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
13530c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
13540c7d97c5SJed Brown   PetscMPIInt master_proc=0;
13550c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
13560c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
13575b08dc53SStefano Zampini   PetscMPIInt *ranks_recv=0;
13580c7d97c5SJed Brown   PetscMPIInt count_recv=0;
13595b08dc53SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
13600c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
13610c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
13620c7d97c5SJed Brown   /* some other variables */
13630c7d97c5SJed Brown   PetscErrorCode ierr;
136419fd82e9SBarry Smith   MatType coarse_mat_type;
136519fd82e9SBarry Smith   PCType  coarse_pc_type;
136619fd82e9SBarry Smith   KSPType coarse_ksp_type;
136753cdbc3dSStefano Zampini   PC pc_temp;
13684fad6a16SStefano Zampini   PetscInt i,j,k;
13693b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1370e269702eSStefano Zampini   /* verbose output viewer */
1371e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
13725b08dc53SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
1373142dfd88SStefano Zampini 
1374ea7e1babSStefano Zampini   PetscInt      offset,offset2;
1375a929c220SStefano Zampini   PetscMPIInt   im_active,active_procs;
1376523858cfSStefano Zampini   PetscInt      *dnz,*onz;
1377142dfd88SStefano Zampini 
1378142dfd88SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
13790c7d97c5SJed Brown 
13800c7d97c5SJed Brown   PetscFunctionBegin;
13814b2d0b89SJed Brown   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
13820c7d97c5SJed Brown   ins_local_primal_indices = 0;
13830c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
13840c7d97c5SJed Brown   localsizes2              = 0;
13850c7d97c5SJed Brown   localdispl2              = 0;
13860c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
13870c7d97c5SJed Brown   coarse_ISLG              = 0;
13880c7d97c5SJed Brown 
138953cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
139053cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
1391142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
1392142dfd88SStefano Zampini 
1393beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1394beed3852SStefano Zampini   {
1395674ae819SStefano Zampini     PetscInt     *auxlocal_primal,*aux_idx;
1396ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
1397ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
1398ef028eecSStefano Zampini 
1399ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1400beed3852SStefano Zampini 
1401beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1402ffe5efe1SStefano Zampini     j = 0;
1403142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1404ffe5efe1SStefano Zampini       j = size_prec_comm;
1405ffe5efe1SStefano Zampini     }
1406ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1407ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1408beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
1409142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
14105619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1411ffe5efe1SStefano Zampini     } else {
1412ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1413ffe5efe1SStefano Zampini     }
1414beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1415ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
1416beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1417beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1418beed3852SStefano Zampini     }
1419beed3852SStefano Zampini 
1420da1bb401SStefano Zampini     /* First let's count coarse dofs.
1421beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1422beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1423beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1424ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
1425674ae819SStefano Zampini     ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
1426674ae819SStefano Zampini     ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
1427674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1428674ae819SStefano Zampini     ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
1429674ae819SStefano Zampini     ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
1430674ae819SStefano Zampini     ierr = PetscFree(aux_idx);CHKERRQ(ierr);
1431ef028eecSStefano Zampini     /* Compute number of coarse dofs */
1432674ae819SStefano Zampini     ierr = PCBDDCSubsetNumbering(prec_comm,matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&pcbddc->coarse_size,&pcbddc->local_primal_indices);CHKERRQ(ierr);
1433ef028eecSStefano Zampini 
1434ef028eecSStefano Zampini     if (dbg_flag) {
14352e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14362e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14372e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
14382e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
14392e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14402fa5cd67SKarl Rupp       for (i=0;i<pcbddc->local_primal_size;i++) array[auxlocal_primal[i]]=1.0;
1441beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14422e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1443da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1444da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1445da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1446da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1447da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14482e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14492e8d2280SStefano Zampini         if (array[i] == 1.0) {
14502e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
14512e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
14522e8d2280SStefano Zampini         }
14532e8d2280SStefano Zampini       }
14542e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14552e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
14565b08dc53SStefano Zampini         if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
14572e8d2280SStefano Zampini       }
1458da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14592e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1460da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1461da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1462da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
14632e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
14642e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14652e8d2280SStefano Zampini     }
1466142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
14670bdf917eSStefano Zampini   }
14680bdf917eSStefano Zampini 
14692e8d2280SStefano Zampini   if (dbg_flag) {
14707cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
14719d9e44b6SStefano Zampini     if (dbg_flag > 1) {
1472674ae819SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
14732e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1474674ae819SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1475674ae819SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
1476674ae819SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1477674ae819SStefano Zampini       }
14782e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14792e8d2280SStefano Zampini     }
14802e8d2280SStefano Zampini   }
14812e8d2280SStefano Zampini 
1482a929c220SStefano Zampini   im_active = 0;
14832fa5cd67SKarl Rupp   if (pcis->n) im_active = 1;
1484a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
14850bdf917eSStefano Zampini 
14860bdf917eSStefano Zampini   /* adapt coarse problem type */
14877cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
14884fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
14894fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
1490a929c220SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
14910bdf917eSStefano Zampini         if (dbg_flag) {
1492a929c220SStefano 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);
14930bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14940bdf917eSStefano Zampini         }
14950bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
1496142dfd88SStefano Zampini       }
14974fad6a16SStefano Zampini     } else {
14984fad6a16SStefano Zampini       if (dbg_flag) {
1499a929c220SStefano 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);
15004fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
15014fad6a16SStefano Zampini       }
15024fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
15034fad6a16SStefano Zampini     }
15044fad6a16SStefano Zampini   }
15057cbb387bSStefano Zampini #else
15067cbb387bSStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
15077cbb387bSStefano Zampini #endif
1508beed3852SStefano Zampini 
15090c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
15100c7d97c5SJed Brown 
1511da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
15120c7d97c5SJed Brown     {
15137cbb387bSStefano Zampini #if defined(PETSC_HAVE_METIS)
15140c7d97c5SJed Brown       /* we need additional variables */
15150c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15160c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
15170c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
15180c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15190c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15200c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15210c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15220c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15230c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15240c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15250c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15260c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15270c7d97c5SJed Brown       MetisInt    *faces_xadj;
15280c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15290c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15300c7d97c5SJed Brown       PetscInt    *array_int;
15310c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15320c7d97c5SJed Brown       PetscMPIInt total_faces=0;
15333828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
15340c7d97c5SJed Brown 
15350c7d97c5SJed Brown       /* define some quantities */
15360c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15370c7d97c5SJed Brown       coarse_mat_type = MATIS;
15380c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
1539142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
15400c7d97c5SJed Brown 
15410c7d97c5SJed Brown       /* details of coarse decomposition */
1542a929c220SStefano Zampini       n_subdomains = active_procs;
15430c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1544a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
15453828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
15463828260eSStefano Zampini 
1547a929c220SStefano Zampini #if 0
1548a929c220SStefano Zampini       PetscMPIInt *old_ranks;
1549a929c220SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
1550a929c220SStefano Zampini       MatPartitioning mat_part;
1551a929c220SStefano Zampini       IS coarse_new_decomposition,is_numbering;
1552a929c220SStefano Zampini       PetscViewer viewer_test;
1553a929c220SStefano Zampini       MPI_Comm    test_coarse_comm;
1554a929c220SStefano Zampini       PetscMPIInt test_coarse_color;
1555a929c220SStefano Zampini       Mat         mat_adj;
1556a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
1557a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1558a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
1559a929c220SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
1560a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
1561a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
1562a929c220SStefano Zampini       if (im_active) {
1563a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
1564a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
1565a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
1566a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
1567a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
1568674ae819SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
1569674ae819SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
1570a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
1571a929c220SStefano Zampini         k = pcis->n_neigh-1;
1572a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
1573a929c220SStefano Zampini         ii[0]=0;
1574a929c220SStefano Zampini         ii[1]=k;
1575a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
1576674ae819SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
1577a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
15780298fd71SBarry Smith         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
1579a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
1580a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
1581a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
1582a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
1583a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
1584a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
1585a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
1586a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
1587a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
1588a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
1589a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
1590a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
1591a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
1592a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
1593a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
1594a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
1595a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
1596a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
1597a929c220SStefano Zampini       }
1598a929c220SStefano Zampini #endif
1599a929c220SStefano Zampini 
16004fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
16010c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
16023828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
16030c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
16040c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16050c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
16060c7d97c5SJed Brown         }
16070c7d97c5SJed Brown       }
16080c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16090c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16107cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16110c7d97c5SJed Brown             my_faces++;
16120c7d97c5SJed Brown             break;
16130c7d97c5SJed Brown           }
16140c7d97c5SJed Brown         }
16150c7d97c5SJed Brown       }
16160c7d97c5SJed Brown 
161753cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
16180c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
16190c7d97c5SJed Brown       my_faces=0;
16200c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++){
16210c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++){
16227cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
16230c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
16240c7d97c5SJed Brown             my_faces++;
16250c7d97c5SJed Brown             break;
16260c7d97c5SJed Brown           }
16270c7d97c5SJed Brown         }
16280c7d97c5SJed Brown       }
16290c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16300c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
16310c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
16320c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
16330c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
16340c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
16350c7d97c5SJed Brown       }
163653cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16370c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16380c7d97c5SJed Brown         faces_xadj[0]=0;
16390c7d97c5SJed Brown         faces_displacements[0]=0;
16400c7d97c5SJed Brown         j=0;
16410c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
16420c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
16430c7d97c5SJed Brown           if (number_of_faces[i-1]) {
16440c7d97c5SJed Brown             j++;
16450c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
16460c7d97c5SJed Brown           }
16470c7d97c5SJed Brown         }
16480c7d97c5SJed Brown       }
164953cdbc3dSStefano 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);
16500c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
16510c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
16520c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
16533828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
16540c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16550c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16560c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16570c7d97c5SJed Brown       }
16580c7d97c5SJed Brown 
16590c7d97c5SJed Brown       if ( rank_prec_comm == master_proc ) {
1660674ae819SStefano Zampini 
16613828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
1662674ae819SStefano Zampini 
16630c7d97c5SJed Brown         ncon=1;
16640c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16650c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16660c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16670c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16680c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16690c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16700c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16714fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
16723828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
16733828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
16743828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16750c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1676674ae819SStefano 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);
16773828260eSStefano Zampini           } else {
16783828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1679674ae819SStefano 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);
16803828260eSStefano Zampini           }
16814fad6a16SStefano Zampini         } else {
16822fa5cd67SKarl Rupp           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
16834fad6a16SStefano Zampini         }
16840c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
16850c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
16860bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
16872fa5cd67SKarl Rupp 
16880c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
16892fa5cd67SKarl Rupp         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
16902fa5cd67SKarl Rupp         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
16910c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
16920c7d97c5SJed Brown       }
16930c7d97c5SJed Brown 
16940c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
16950c7d97c5SJed Brown       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
1696da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
1697da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
16980c7d97c5SJed Brown       }
1699da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1700da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
170153cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
17020c7d97c5SJed Brown 
17030c7d97c5SJed Brown       if ( coarse_color == 0 ) {
170453cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
170553cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
17060c7d97c5SJed Brown       } else {
17070c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
17080c7d97c5SJed Brown       }
17090c7d97c5SJed Brown 
17107cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
17110c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
17120c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
17130bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
17140bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
17150c7d97c5SJed Brown         /* some initializations */
17160c7d97c5SJed Brown         displacements_recv[0]=0;
17170bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17180c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
17190bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
17200bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17212fa5cd67SKarl Rupp           if (coarse_subdivision[i]==j) total_count_recv[j]++;
17220bdf917eSStefano Zampini           }
17230bdf917eSStefano Zampini         }
17240c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
17252fa5cd67SKarl Rupp       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
17262fa5cd67SKarl Rupp 
17270c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
17280c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17290c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
17303828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
17310c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
17320c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
17333828260eSStefano Zampini               total_count_recv[j]+=1;
17340c7d97c5SJed Brown             }
17350c7d97c5SJed Brown           }
17360c7d97c5SJed Brown         }
1737da1bb401SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
17383828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
17393828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
17403828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
17413828260eSStefano Zampini           }
17423828260eSStefano Zampini           printf("\n");
1743da1bb401SStefano Zampini         }*/
17440c7d97c5SJed Brown 
17450c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
17460bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
17470bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
17480bdf917eSStefano Zampini         }
1749da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
1750674ae819SStefano Zampini         for (i=0;i<size_prec_comm;i++)
17513828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
17523828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
17533828260eSStefano Zampini           } else {
17543828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
17553828260eSStefano Zampini           }
1756da1bb401SStefano Zampini         printf("\n");*/
17570c7d97c5SJed Brown       }
17580c7d97c5SJed Brown 
17590c7d97c5SJed Brown       /* Scatter new decomposition for send details */
176053cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
17610c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17620c7d97c5SJed Brown       if ( coarse_color == 0) {
176353cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17640c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
176553cdbc3dSStefano 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);
17660c7d97c5SJed Brown       }
17670c7d97c5SJed Brown 
1768da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
1769da1bb401SStefano Zampini       if (coarse_color == 0) {
1770da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
1771da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
1772da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
1773da1bb401SStefano Zampini         printf("\n");
1774da1bb401SStefano Zampini       }*/
17750c7d97c5SJed Brown 
17760c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
17770bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
1778da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17790bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17800c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17810c7d97c5SJed Brown       }
17827cbb387bSStefano Zampini #endif
17830c7d97c5SJed Brown       break;
17840c7d97c5SJed Brown     }
17850c7d97c5SJed Brown 
17860c7d97c5SJed Brown     case(REPLICATED_BDDC):
17870c7d97c5SJed Brown 
17880c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17890c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17900c7d97c5SJed Brown       coarse_pc_type  = PCLU;
179153cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17920c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
17930c7d97c5SJed Brown       active_rank = rank_prec_comm;
17940c7d97c5SJed Brown       break;
17950c7d97c5SJed Brown 
17960c7d97c5SJed Brown     case(PARALLEL_BDDC):
17970c7d97c5SJed Brown 
17980c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1799674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18000c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
180153cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18020c7d97c5SJed Brown       coarse_comm = prec_comm;
18030c7d97c5SJed Brown       active_rank = rank_prec_comm;
18040c7d97c5SJed Brown       break;
18050c7d97c5SJed Brown 
18060c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
18070c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
1808674ae819SStefano Zampini       coarse_mat_type = MATAIJ;
18090c7d97c5SJed Brown       coarse_pc_type = PCLU;
181053cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18110c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18120c7d97c5SJed Brown       active_rank = master_proc;
18130c7d97c5SJed Brown       break;
18140c7d97c5SJed Brown   }
18150c7d97c5SJed Brown 
18160c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
18170c7d97c5SJed Brown 
18180c7d97c5SJed Brown     case(SCATTERS_BDDC):
18190c7d97c5SJed Brown       {
18200c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
18210c7d97c5SJed Brown 
18222e8d2280SStefano Zampini           IS coarse_IS;
18232e8d2280SStefano Zampini 
1824523858cfSStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
1825523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
1826523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
1827523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
1828523858cfSStefano Zampini             /* nonzeros */
1829523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1830523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
1831523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1832523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
1833523858cfSStefano Zampini             }
1834523858cfSStefano Zampini           } else {
18350c7d97c5SJed Brown             PetscMPIInt send_size;
1836ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
18370c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
18380c7d97c5SJed Brown             PetscInt    ii,jj;
18390c7d97c5SJed Brown             MPI_Request *requests;
1840ef028eecSStefano Zampini 
1841523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
1842523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
1843523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
1844523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1845523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
1846523858cfSStefano Zampini             j = 0;
1847523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1848523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
1849523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
1850523858cfSStefano Zampini             }
1851523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
1852523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
18530c7d97c5SJed Brown             /* allocate auxiliary space */
1854523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
18550c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
18560c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
18570c7d97c5SJed Brown             /* allocate stuffs for message massing */
18580c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
1859523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
1860523858cfSStefano Zampini             /* send indices to be inserted */
1861523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1862523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
1863523858cfSStefano 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);
1864523858cfSStefano Zampini             }
1865523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1866523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
1867ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
1868ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
1869ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
1870ef028eecSStefano Zampini               }
1871ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
1872523858cfSStefano Zampini             }
1873523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1874ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1875ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
1876ef028eecSStefano Zampini             }
18770c7d97c5SJed Brown             j = 0;
18780c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
18792e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
18802e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
18810c7d97c5SJed Brown               localdispl2[i] = j;
18820c7d97c5SJed Brown               j += localsizes2[i];
1883523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
18844fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
18852e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
18864fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
18870c7d97c5SJed Brown               }
18884fad6a16SStefano Zampini             }
1889523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
18900c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
18910c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
18920c7d97c5SJed Brown             ins_local_primal_size = 0;
1893ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
1894ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
18950c7d97c5SJed Brown                 ins_local_primal_size++;
1896ea7e1babSStefano Zampini               }
1897ea7e1babSStefano Zampini             }
18980c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
18990c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19000c7d97c5SJed Brown             j = 0;
1901ea7e1babSStefano Zampini             for(i=0;i<pcbddc->coarse_size;i++) {
1902ea7e1babSStefano Zampini               if(aux_ins_indices[i]) {
19032e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
19042e8d2280SStefano Zampini                 j++;
1905ea7e1babSStefano Zampini               }
1906ea7e1babSStefano Zampini             }
1907523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
1908523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
1909523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
1910523858cfSStefano Zampini             }
1911523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1912523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
1913523858cfSStefano 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);
1914523858cfSStefano Zampini             }
1915523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
1916523858cfSStefano Zampini             /* nonzeros */
1917523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
1918523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
19190c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
19200c7d97c5SJed Brown             j=0;
19210c7d97c5SJed Brown             for(i=0;i<pcbddc->coarse_size;i++){
19220c7d97c5SJed Brown               if(aux_ins_indices[i]==0){
19230c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
19240c7d97c5SJed Brown               } else {
19250c7d97c5SJed Brown                 aux_ins_indices[i]=j;
19260c7d97c5SJed Brown                 j++;
19270c7d97c5SJed Brown               }
19280c7d97c5SJed Brown             }
19294fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
1930523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
1931523858cfSStefano Zampini               for (k=0;k<j;k++) {
1932523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
19330c7d97c5SJed Brown               }
19340c7d97c5SJed Brown             }
1935523858cfSStefano Zampini             /* check */
1936523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
1937523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
1938523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
19390c7d97c5SJed Brown               }
19400c7d97c5SJed Brown             }
19410c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
19420c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
19430c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
19444fad6a16SStefano Zampini           }
19450c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
1946142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
19470c7d97c5SJed Brown           coarse_comm = prec_comm;
19480c7d97c5SJed Brown           active_rank = rank_prec_comm;
19490c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
19500c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
19510c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
19522e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
19530c7d97c5SJed Brown           /* arrays for values insertion */
19540c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
19552e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19560c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19570c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++){
19580c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
19594fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
19604fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
19614fad6a16SStefano Zampini             }
19620c7d97c5SJed Brown           }
19630c7d97c5SJed Brown         }
19640c7d97c5SJed Brown         break;
1965674ae819SStefano Zampini 
19660c7d97c5SJed Brown     }
19670c7d97c5SJed Brown 
19680c7d97c5SJed Brown     case(GATHERS_BDDC):
19690c7d97c5SJed Brown       {
1970674ae819SStefano Zampini 
19710c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
1972ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
19730c7d97c5SJed Brown 
19740c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
19750c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19760bdf917eSStefano Zampini           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
19770c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19780c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19790c7d97c5SJed Brown           /* arrays for values insertion */
19802fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19810c7d97c5SJed Brown           localdispl2[0]=0;
19822fa5cd67SKarl Rupp       for (i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
19830c7d97c5SJed Brown           j=0;
19842fa5cd67SKarl Rupp       for (i=0;i<size_prec_comm;i++) j+=localsizes2[i];
19850c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19860c7d97c5SJed Brown         }
19870c7d97c5SJed Brown 
19880c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
19890c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
1990ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
19912fa5cd67SKarl Rupp     for (i=0; i<mysize; i++) send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
19922fa5cd67SKarl Rupp 
19930c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
1994ef028eecSStefano 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);
199553cdbc3dSStefano 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);
19960c7d97c5SJed Brown         } else {
1997ef028eecSStefano 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);
199853cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
19990c7d97c5SJed Brown         }
2000ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
20010c7d97c5SJed Brown         break;
2002da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
20030c7d97c5SJed Brown   }
20040c7d97c5SJed Brown 
20050c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
20060c7d97c5SJed Brown   if ( rank_prec_comm == active_rank ) {
2007142dfd88SStefano Zampini 
2008142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
2009142dfd88SStefano Zampini 
20100c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
20110c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
20120c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
20130c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2014674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2015674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20163b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2017da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
20183b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20190c7d97c5SJed Brown     } else {
20204fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
20213b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
20220c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2023674ae819SStefano Zampini       ierr = MatSetOptionsPrefix(pcbddc->coarse_mat,"coarse_");CHKERRQ(ierr);
2024674ae819SStefano Zampini       ierr = MatSetFromOptions(pcbddc->coarse_mat);CHKERRQ(ierr);
20253b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2026da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2027a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20280c7d97c5SJed Brown     }
2029142dfd88SStefano Zampini     /* preallocation */
2030142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2031ef028eecSStefano Zampini 
2032674ae819SStefano Zampini       PetscInt lrows,lcols,bs;
2033ef028eecSStefano Zampini 
2034142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2035142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2036674ae819SStefano Zampini       ierr = MatGetBlockSize(pcbddc->coarse_mat,&bs);CHKERRQ(ierr);
2037ef028eecSStefano Zampini 
2038142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2039ef028eecSStefano Zampini 
2040ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
2041ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2042ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2043ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2044ef028eecSStefano Zampini 
2045ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2046674ae819SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2047ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
2048ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2049ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2050ef028eecSStefano Zampini 
2051ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2052ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2053ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2054ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2055ef028eecSStefano Zampini 
2056ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2057ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2058142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2059ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2060ef028eecSStefano Zampini             row_ownership[j]=i;
2061142dfd88SStefano Zampini           }
2062142dfd88SStefano Zampini         }
2063ef028eecSStefano Zampini 
2064ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2065ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
2066ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
2067ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2068ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
2069ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
2070ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2071ef028eecSStefano Zampini               my_dnz[i] += 1.0;
2072142dfd88SStefano Zampini             } else {
2073ef028eecSStefano Zampini               my_onz[i] += 1.0;
2074142dfd88SStefano Zampini             }
2075ef028eecSStefano Zampini             if (i != j) {
2076ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
2077ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2078ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
2079142dfd88SStefano Zampini               } else {
2080ef028eecSStefano Zampini                 my_onz[j] += 1.0;
2081142dfd88SStefano Zampini               }
2082142dfd88SStefano Zampini             }
2083142dfd88SStefano Zampini           }
2084142dfd88SStefano Zampini         }
2085ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2086ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2087a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
2088ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2089ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2090a929c220SStefano Zampini         }
2091ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2092ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2093ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2094ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2095ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2096ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
20975b08dc53SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
20982fa5cd67SKarl Rupp 
2099ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2100ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
21015b08dc53SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
21022fa5cd67SKarl Rupp 
2103ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2104ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2105ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2106ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2107ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2108ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2109142dfd88SStefano Zampini       } else {
2110142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++){
2111142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
2112142dfd88SStefano Zampini           offset2=localdispl2[k];
2113142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
2114ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2115ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2116ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2117ef028eecSStefano Zampini           }
2118142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
2119142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
2120142dfd88SStefano Zampini           }
2121ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2122142dfd88SStefano Zampini         }
2123142dfd88SStefano Zampini       }
21242fa5cd67SKarl Rupp 
2125142dfd88SStefano Zampini       /* check */
2126142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
21272fa5cd67SKarl Rupp         if (dnz[i]>lcols) dnz[i]=lcols;
21282fa5cd67SKarl Rupp         if (onz[i]>pcbddc->coarse_size-lcols) onz[i]=pcbddc->coarse_size-lcols;
2129142dfd88SStefano Zampini       }
2130d9a4edebSJed Brown       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,0,dnz);CHKERRQ(ierr);
2131d9a4edebSJed Brown       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2132142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2133142dfd88SStefano Zampini     } else {
2134523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2135523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2136142dfd88SStefano Zampini     }
2137142dfd88SStefano Zampini     /* insert values */
2138523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
21390c7d97c5SJed 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);
2140523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2141523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2142523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2143523858cfSStefano 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);
2144523858cfSStefano Zampini       } else {
2145523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2146523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
2147523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
2148523858cfSStefano Zampini           offset2 = localdispl2[k];
2149523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
2150ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2151ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2152ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2153ef028eecSStefano Zampini           }
2154523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2155523858cfSStefano 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);
2156ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2157523858cfSStefano Zampini         }
2158523858cfSStefano Zampini       }
2159523858cfSStefano Zampini       ins_local_primal_indices = 0;
2160523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
2161ea7e1babSStefano Zampini     } else {
2162ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++){
2163ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
2164ea7e1babSStefano Zampini         offset2=localdispl2[k];
2165ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
2166ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2167ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++){
2168ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
2169ef028eecSStefano Zampini         }
2170ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2171ea7e1babSStefano 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);
2172ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2173ea7e1babSStefano Zampini       }
2174ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
2175ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
2176ea7e1babSStefano Zampini     }
21770c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21780c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2179142dfd88SStefano Zampini     /* symmetry of coarse matrix */
2180142dfd88SStefano Zampini     if (issym) {
2181142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2182142dfd88SStefano Zampini     }
21830c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
21840bdf917eSStefano Zampini   }
21850bdf917eSStefano Zampini 
21860bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
21870bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
21880bdf917eSStefano Zampini      IS local_IS,global_IS;
21890bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
21900bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
21910bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
21920bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
21930bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
21940bdf917eSStefano Zampini   }
21950bdf917eSStefano Zampini 
2196a929c220SStefano Zampini   /* free memory no longer needed */
2197a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2198a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2199a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2200a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2201a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2202a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2203a929c220SStefano Zampini 
2204674ae819SStefano Zampini   /* Compute coarse null space */
2205674ae819SStefano Zampini   CoarseNullSpace = 0;
22060bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
2207674ae819SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,&CoarseNullSpace);CHKERRQ(ierr);
22080bdf917eSStefano Zampini   }
22090bdf917eSStefano Zampini 
22100bdf917eSStefano Zampini   /* KSP for coarse problem */
22110bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
22122e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
22130bdf917eSStefano Zampini 
221453cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
221553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
221653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22173b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
221853cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
221953cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
222053cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
22210c7d97c5SJed Brown     /* Allow user's customization */
2222da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
22230c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
222453cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22254fad6a16SStefano Zampini       i = pcbddc->current_level+1;
22264fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
22274fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
22284fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
222953cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2230674ae819SStefano Zampini       if (CoarseNullSpace) {
2231674ae819SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2232674ae819SStefano Zampini       }
22334fad6a16SStefano Zampini       if (dbg_flag) {
22344fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
22354fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
223653cdbc3dSStefano Zampini       }
2237674ae819SStefano Zampini     } else {
2238674ae819SStefano Zampini       if (CoarseNullSpace) {
2239674ae819SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2240674ae819SStefano Zampini       }
22414fad6a16SStefano Zampini     }
22424fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
224353cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2244142dfd88SStefano Zampini 
22450298fd71SBarry Smith     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
22462e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
22472e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
22482e8d2280SStefano Zampini     if (j == 1) {
22492e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
22502e8d2280SStefano Zampini       if (isbddc) {
22512e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
22525619798eSStefano Zampini       }
22535619798eSStefano Zampini     }
22540c7d97c5SJed Brown   }
2255a929c220SStefano Zampini   /* Check coarse problem if requested */
2256142dfd88SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2257142dfd88SStefano Zampini     KSP check_ksp;
2258142dfd88SStefano Zampini     PC  check_pc;
2259142dfd88SStefano Zampini     Vec check_vec;
2260142dfd88SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
226119fd82e9SBarry Smith     KSPType check_ksp_type;
22620c7d97c5SJed Brown 
2263142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2264142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2265142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
22660bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
2267142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
22682fa5cd67SKarl Rupp       if (issym) check_ksp_type = KSPCG;
22692fa5cd67SKarl Rupp       else check_ksp_type = KSPGMRES;
2270142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
2271142dfd88SStefano Zampini     } else {
2272142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
2273142dfd88SStefano Zampini     }
2274142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
2275142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
2276142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
2277142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
2278142dfd88SStefano Zampini     /* create random vec */
2279142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
22800298fd71SBarry Smith     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
2281674ae819SStefano Zampini     if (CoarseNullSpace) {
22821cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
2283674ae819SStefano Zampini     }
2284142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2285142dfd88SStefano Zampini     /* solve coarse problem */
2286142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2287674ae819SStefano Zampini     if (CoarseNullSpace) {
22881cb54aadSJed Brown       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
2289674ae819SStefano Zampini     }
2290142dfd88SStefano Zampini     /* check coarse problem residual error */
2291142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
2292142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
2293142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2294142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
2295142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
2296142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
2297142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2298142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
2299142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
2300142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
2301e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
23023b03a366Sstefano_zampini     }
2303142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
2304142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
2305142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
230653cdbc3dSStefano Zampini   }
2307674ae819SStefano Zampini   if (dbg_flag) {
2308da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2309da1bb401SStefano Zampini   }
2310674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
2311a0ba757dSStefano Zampini 
23120c7d97c5SJed Brown   PetscFunctionReturn(0);
23130c7d97c5SJed Brown }
23140c7d97c5SJed Brown 
2315