xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision c5df96a59d3f7e354f9770fb35f00818af2dc9fc)
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
7a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
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 
2207475bc1SBarry Smith #include "bddc.h" /*I "petscpc.h" I*/
233b03a366Sstefano_zampini #include <petscblaslapack.h>
240c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
250c7d97c5SJed Brown #undef __FUNCT__
260c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
270c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
280c7d97c5SJed Brown {
290c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
300c7d97c5SJed Brown   PetscErrorCode ierr;
310c7d97c5SJed Brown 
320c7d97c5SJed Brown   PetscFunctionBegin;
330c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
340c7d97c5SJed Brown   /* Verbose debugging of main data structures */
35e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
360c7d97c5SJed Brown   /* Some customization for default primal space */
37da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use only vertices in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
38da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use only constraints in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
39da1bb401SStefano Zampini   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      ,PETSC_NULL);CHKERRQ(ierr);
40da1bb401SStefano Zampini   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      ,PETSC_NULL);CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Coarse solver context */
426c667b0aSStefano 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 */
430c7d97c5SJed Brown   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,PETSC_NULL);CHKERRQ(ierr);
440c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
4529622bf0SStefano Zampini   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,PETSC_NULL);CHKERRQ(ierr);
46534831adSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use change of basis approach for primal space","none",pcbddc->usechangeofbasis,&pcbddc->usechangeofbasis,PETSC_NULL);CHKERRQ(ierr);
47534831adSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use change of basis approach for face constraints","none",pcbddc->usechangeonfaces,&pcbddc->usechangeonfaces,PETSC_NULL);CHKERRQ(ierr);
48534831adSStefano Zampini   pcbddc->usechangeonfaces = pcbddc->usechangeonfaces && pcbddc->usechangeofbasis;
490c7d97c5SJed Brown   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr);
504fad6a16SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_max_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,PETSC_NULL);CHKERRQ(ierr);
510c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
520c7d97c5SJed Brown   PetscFunctionReturn(0);
530c7d97c5SJed Brown }
540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
550c7d97c5SJed Brown EXTERN_C_BEGIN
560c7d97c5SJed Brown #undef __FUNCT__
570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
5853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
590c7d97c5SJed Brown {
600c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
610c7d97c5SJed Brown 
620c7d97c5SJed Brown   PetscFunctionBegin;
630c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
640c7d97c5SJed Brown   PetscFunctionReturn(0);
650c7d97c5SJed Brown }
660c7d97c5SJed Brown EXTERN_C_END
670c7d97c5SJed Brown #undef __FUNCT__
680c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
6953cdbc3dSStefano Zampini /*@
709c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7153cdbc3dSStefano Zampini 
729c0446d6SStefano Zampini    Not collective
7353cdbc3dSStefano Zampini 
7453cdbc3dSStefano Zampini    Input Parameters:
7553cdbc3dSStefano Zampini +  pc - the preconditioning context
7653cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
7753cdbc3dSStefano Zampini 
7853cdbc3dSStefano Zampini    Level: intermediate
7953cdbc3dSStefano Zampini 
8053cdbc3dSStefano Zampini    Notes:
81da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
8253cdbc3dSStefano Zampini 
8353cdbc3dSStefano Zampini .seealso: PCBDDC
8453cdbc3dSStefano Zampini @*/
850c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
860c7d97c5SJed Brown {
870c7d97c5SJed Brown   PetscErrorCode ierr;
880c7d97c5SJed Brown 
890c7d97c5SJed Brown   PetscFunctionBegin;
900c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
910c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
920c7d97c5SJed Brown   PetscFunctionReturn(0);
930c7d97c5SJed Brown }
940c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
950c7d97c5SJed Brown EXTERN_C_BEGIN
960c7d97c5SJed Brown #undef __FUNCT__
974fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
984fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
994fad6a16SStefano Zampini {
1004fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1014fad6a16SStefano Zampini 
1024fad6a16SStefano Zampini   PetscFunctionBegin;
1034fad6a16SStefano Zampini   pcbddc->coarsening_ratio=k;
1044fad6a16SStefano Zampini   PetscFunctionReturn(0);
1054fad6a16SStefano Zampini }
1064fad6a16SStefano Zampini EXTERN_C_END
1074fad6a16SStefano Zampini #undef __FUNCT__
1084fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
1094fad6a16SStefano Zampini /*@
1104fad6a16SStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening
1114fad6a16SStefano Zampini 
1124fad6a16SStefano Zampini    Logically collective on PC
1134fad6a16SStefano Zampini 
1144fad6a16SStefano Zampini    Input Parameters:
1154fad6a16SStefano Zampini +  pc - the preconditioning context
1164fad6a16SStefano Zampini -  k - coarsening ratio
1174fad6a16SStefano Zampini 
1184fad6a16SStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level.
1194fad6a16SStefano Zampini 
1204fad6a16SStefano Zampini    Level: intermediate
1214fad6a16SStefano Zampini 
1224fad6a16SStefano Zampini    Notes:
1234fad6a16SStefano Zampini 
1244fad6a16SStefano Zampini .seealso: PCBDDC
1254fad6a16SStefano Zampini @*/
1264fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
1274fad6a16SStefano Zampini {
1284fad6a16SStefano Zampini   PetscErrorCode ierr;
1294fad6a16SStefano Zampini 
1304fad6a16SStefano Zampini   PetscFunctionBegin;
1314fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1324fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
1334fad6a16SStefano Zampini   PetscFunctionReturn(0);
1344fad6a16SStefano Zampini }
1354fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1364fad6a16SStefano Zampini EXTERN_C_BEGIN
1374fad6a16SStefano Zampini #undef __FUNCT__
1384fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels_BDDC"
1394fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetMaxLevels_BDDC(PC pc,PetscInt max_levels)
1404fad6a16SStefano Zampini {
1414fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1424fad6a16SStefano Zampini 
1434fad6a16SStefano Zampini   PetscFunctionBegin;
1444fad6a16SStefano Zampini   pcbddc->max_levels=max_levels;
1454fad6a16SStefano Zampini   PetscFunctionReturn(0);
1464fad6a16SStefano Zampini }
1474fad6a16SStefano Zampini EXTERN_C_END
1484fad6a16SStefano Zampini #undef __FUNCT__
1494fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetMaxLevels"
1504fad6a16SStefano Zampini /*@
1514fad6a16SStefano Zampini  PCBDDCSetMaxLevels - Sets the maximum number of levels within the multilevel approach.
1524fad6a16SStefano Zampini 
1534fad6a16SStefano Zampini    Logically collective on PC
1544fad6a16SStefano Zampini 
1554fad6a16SStefano Zampini    Input Parameters:
1564fad6a16SStefano Zampini +  pc - the preconditioning context
1574fad6a16SStefano Zampini -  max_levels - the maximum number of levels
1584fad6a16SStefano Zampini 
1594fad6a16SStefano Zampini    Default value is 1, i.e. coarse problem will be solved inexactly with one application
1604fad6a16SStefano Zampini    of PCBDDC preconditioner if the multilevel approach is requested.
1614fad6a16SStefano Zampini 
1624fad6a16SStefano Zampini    Level: intermediate
1634fad6a16SStefano Zampini 
1644fad6a16SStefano Zampini    Notes:
1654fad6a16SStefano Zampini 
1664fad6a16SStefano Zampini .seealso: PCBDDC
1674fad6a16SStefano Zampini @*/
1684fad6a16SStefano Zampini PetscErrorCode PCBDDCSetMaxLevels(PC pc,PetscInt max_levels)
1694fad6a16SStefano Zampini {
1704fad6a16SStefano Zampini   PetscErrorCode ierr;
1714fad6a16SStefano Zampini 
1724fad6a16SStefano Zampini   PetscFunctionBegin;
1734fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1744fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetMaxLevels_C",(PC,PetscInt),(pc,max_levels));CHKERRQ(ierr);
1754fad6a16SStefano Zampini   PetscFunctionReturn(0);
1764fad6a16SStefano Zampini }
1774fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
1784fad6a16SStefano Zampini EXTERN_C_BEGIN
1794fad6a16SStefano Zampini #undef __FUNCT__
1800bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
1810bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
1820bdf917eSStefano Zampini {
1830bdf917eSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1840bdf917eSStefano Zampini   PetscErrorCode ierr;
1850bdf917eSStefano Zampini 
1860bdf917eSStefano Zampini   PetscFunctionBegin;
1870bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
1880bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
1890bdf917eSStefano Zampini   pcbddc->NullSpace=NullSpace;
1900bdf917eSStefano Zampini   PetscFunctionReturn(0);
1910bdf917eSStefano Zampini }
1920bdf917eSStefano Zampini EXTERN_C_END
1930bdf917eSStefano Zampini #undef __FUNCT__
1940bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
1950bdf917eSStefano Zampini /*@
1960bdf917eSStefano Zampini  PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat.
1970bdf917eSStefano Zampini 
1980bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
1990bdf917eSStefano Zampini 
2000bdf917eSStefano Zampini    Input Parameters:
2010bdf917eSStefano Zampini +  pc - the preconditioning context
2020bdf917eSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned.
2030bdf917eSStefano Zampini 
2040bdf917eSStefano Zampini    Level: intermediate
2050bdf917eSStefano Zampini 
2060bdf917eSStefano Zampini    Notes:
2070bdf917eSStefano Zampini 
2080bdf917eSStefano Zampini .seealso: PCBDDC
2090bdf917eSStefano Zampini @*/
2100bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
2110bdf917eSStefano Zampini {
2120bdf917eSStefano Zampini   PetscErrorCode ierr;
2130bdf917eSStefano Zampini 
2140bdf917eSStefano Zampini   PetscFunctionBegin;
2150bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2160bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
2170bdf917eSStefano Zampini   PetscFunctionReturn(0);
2180bdf917eSStefano Zampini }
2190bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
2200bdf917eSStefano Zampini EXTERN_C_BEGIN
2210bdf917eSStefano Zampini #undef __FUNCT__
2223b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
2233b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
2243b03a366Sstefano_zampini {
2253b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2263b03a366Sstefano_zampini   PetscErrorCode ierr;
2273b03a366Sstefano_zampini 
2283b03a366Sstefano_zampini   PetscFunctionBegin;
2293b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
23036e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
23136e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
2323b03a366Sstefano_zampini   PetscFunctionReturn(0);
2333b03a366Sstefano_zampini }
2343b03a366Sstefano_zampini EXTERN_C_END
2353b03a366Sstefano_zampini #undef __FUNCT__
2363b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
2373b03a366Sstefano_zampini /*@
238da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
239da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
2403b03a366Sstefano_zampini 
2413b03a366Sstefano_zampini    Not collective
2423b03a366Sstefano_zampini 
2433b03a366Sstefano_zampini    Input Parameters:
2443b03a366Sstefano_zampini +  pc - the preconditioning context
2453b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
2463b03a366Sstefano_zampini 
2473b03a366Sstefano_zampini    Level: intermediate
2483b03a366Sstefano_zampini 
2493b03a366Sstefano_zampini    Notes:
2503b03a366Sstefano_zampini 
2513b03a366Sstefano_zampini .seealso: PCBDDC
2523b03a366Sstefano_zampini @*/
2533b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
2543b03a366Sstefano_zampini {
2553b03a366Sstefano_zampini   PetscErrorCode ierr;
2563b03a366Sstefano_zampini 
2573b03a366Sstefano_zampini   PetscFunctionBegin;
2583b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2593b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
2603b03a366Sstefano_zampini   PetscFunctionReturn(0);
2613b03a366Sstefano_zampini }
2623b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
2633b03a366Sstefano_zampini EXTERN_C_BEGIN
2643b03a366Sstefano_zampini #undef __FUNCT__
2650c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
26653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
2670c7d97c5SJed Brown {
2680c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
26953cdbc3dSStefano Zampini   PetscErrorCode ierr;
2700c7d97c5SJed Brown 
2710c7d97c5SJed Brown   PetscFunctionBegin;
27253cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
27336e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
27436e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
2750c7d97c5SJed Brown   PetscFunctionReturn(0);
2760c7d97c5SJed Brown }
2770c7d97c5SJed Brown EXTERN_C_END
2780c7d97c5SJed Brown #undef __FUNCT__
2790c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
28057527edcSJed Brown /*@
281da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
282da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
28357527edcSJed Brown 
2849c0446d6SStefano Zampini    Not collective
28557527edcSJed Brown 
28657527edcSJed Brown    Input Parameters:
28757527edcSJed Brown +  pc - the preconditioning context
2889c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
28957527edcSJed Brown 
29057527edcSJed Brown    Level: intermediate
29157527edcSJed Brown 
29257527edcSJed Brown    Notes:
29357527edcSJed Brown 
29457527edcSJed Brown .seealso: PCBDDC
29557527edcSJed Brown @*/
29653cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
2970c7d97c5SJed Brown {
2980c7d97c5SJed Brown   PetscErrorCode ierr;
2990c7d97c5SJed Brown 
3000c7d97c5SJed Brown   PetscFunctionBegin;
3010c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
30253cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
30353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
30453cdbc3dSStefano Zampini }
30553cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
30653cdbc3dSStefano Zampini EXTERN_C_BEGIN
30753cdbc3dSStefano Zampini #undef __FUNCT__
308da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
309da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
310da1bb401SStefano Zampini {
311da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
312da1bb401SStefano Zampini 
313da1bb401SStefano Zampini   PetscFunctionBegin;
314da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
315da1bb401SStefano Zampini   PetscFunctionReturn(0);
316da1bb401SStefano Zampini }
317da1bb401SStefano Zampini EXTERN_C_END
318da1bb401SStefano Zampini #undef __FUNCT__
319da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
320da1bb401SStefano Zampini /*@
321da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
322da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
323da1bb401SStefano Zampini 
324da1bb401SStefano Zampini    Not collective
325da1bb401SStefano Zampini 
326da1bb401SStefano Zampini    Input Parameters:
327da1bb401SStefano Zampini +  pc - the preconditioning context
328da1bb401SStefano Zampini 
329da1bb401SStefano Zampini    Output Parameters:
330da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
331da1bb401SStefano Zampini 
332da1bb401SStefano Zampini    Level: intermediate
333da1bb401SStefano Zampini 
334da1bb401SStefano Zampini    Notes:
335da1bb401SStefano Zampini 
336da1bb401SStefano Zampini .seealso: PCBDDC
337da1bb401SStefano Zampini @*/
338da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
339da1bb401SStefano Zampini {
340da1bb401SStefano Zampini   PetscErrorCode ierr;
341da1bb401SStefano Zampini 
342da1bb401SStefano Zampini   PetscFunctionBegin;
343da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
344da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
345da1bb401SStefano Zampini   PetscFunctionReturn(0);
346da1bb401SStefano Zampini }
347da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
348da1bb401SStefano Zampini EXTERN_C_BEGIN
349da1bb401SStefano Zampini #undef __FUNCT__
35053cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
35153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
35253cdbc3dSStefano Zampini {
35353cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
35453cdbc3dSStefano Zampini 
35553cdbc3dSStefano Zampini   PetscFunctionBegin;
35653cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
35753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
35853cdbc3dSStefano Zampini }
35953cdbc3dSStefano Zampini EXTERN_C_END
36053cdbc3dSStefano Zampini #undef __FUNCT__
36153cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
36253cdbc3dSStefano Zampini /*@
363da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
364da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
36553cdbc3dSStefano Zampini 
3669c0446d6SStefano Zampini    Not collective
36753cdbc3dSStefano Zampini 
36853cdbc3dSStefano Zampini    Input Parameters:
36953cdbc3dSStefano Zampini +  pc - the preconditioning context
37053cdbc3dSStefano Zampini 
37153cdbc3dSStefano Zampini    Output Parameters:
37253cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
37353cdbc3dSStefano Zampini 
37453cdbc3dSStefano Zampini    Level: intermediate
37553cdbc3dSStefano Zampini 
37653cdbc3dSStefano Zampini    Notes:
37753cdbc3dSStefano Zampini 
37853cdbc3dSStefano Zampini .seealso: PCBDDC
37953cdbc3dSStefano Zampini @*/
38053cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
38153cdbc3dSStefano Zampini {
38253cdbc3dSStefano Zampini   PetscErrorCode ierr;
38353cdbc3dSStefano Zampini 
38453cdbc3dSStefano Zampini   PetscFunctionBegin;
38553cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
38653cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
3870c7d97c5SJed Brown   PetscFunctionReturn(0);
3880c7d97c5SJed Brown }
38936e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
39036e030ebSStefano Zampini EXTERN_C_BEGIN
39136e030ebSStefano Zampini #undef __FUNCT__
392da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
3931a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
39436e030ebSStefano Zampini {
39536e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
396da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
397da1bb401SStefano Zampini   PetscErrorCode ierr;
39836e030ebSStefano Zampini 
39936e030ebSStefano Zampini   PetscFunctionBegin;
400da1bb401SStefano Zampini   mat_graph->nvtxs=nvtxs;
401da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->xadj);CHKERRQ(ierr);
402da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->adjncy);CHKERRQ(ierr);
403da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
404da1bb401SStefano Zampini     ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
405da1bb401SStefano Zampini     ierr = PetscMalloc(xadj[mat_graph->nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
406da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
407da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[mat_graph->nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
408da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
4091a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
4101a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
411acee19a7SJed Brown   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d\n",copymode);
41236e030ebSStefano Zampini   PetscFunctionReturn(0);
41336e030ebSStefano Zampini }
41436e030ebSStefano Zampini EXTERN_C_END
41536e030ebSStefano Zampini #undef __FUNCT__
416da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
41736e030ebSStefano Zampini /*@
418da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
41936e030ebSStefano Zampini 
42036e030ebSStefano Zampini    Not collective
42136e030ebSStefano Zampini 
42236e030ebSStefano Zampini    Input Parameters:
42336e030ebSStefano Zampini +  pc - the preconditioning context
424da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
425da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
426da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
427da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
42836e030ebSStefano Zampini 
42936e030ebSStefano Zampini    Level: intermediate
43036e030ebSStefano Zampini 
43136e030ebSStefano Zampini    Notes:
43236e030ebSStefano Zampini 
43336e030ebSStefano Zampini .seealso: PCBDDC
43436e030ebSStefano Zampini @*/
4351a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
43636e030ebSStefano Zampini {
437da1bb401SStefano Zampini   PetscInt       nrows,ncols;
438da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
43936e030ebSStefano Zampini   PetscErrorCode ierr;
44036e030ebSStefano Zampini 
44136e030ebSStefano Zampini   PetscFunctionBegin;
44236e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
443da1bb401SStefano Zampini   ierr = MatGetSize(matis->A,&nrows,&ncols);CHKERRQ(ierr);
444f23aa3ddSBarry Smith   if (nvtxs != nrows) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local adjacency size %d passed in %s differs from local problem size %d!\n",nvtxs,nrows);
445f23aa3ddSBarry Smith   else {
4461a83f524SJed Brown     ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
447da1bb401SStefano Zampini   }
44836e030ebSStefano Zampini   PetscFunctionReturn(0);
44936e030ebSStefano Zampini }
4509c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
4519c0446d6SStefano Zampini EXTERN_C_BEGIN
4529c0446d6SStefano Zampini #undef __FUNCT__
4539c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
4549c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
4559c0446d6SStefano Zampini {
4569c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
4579c0446d6SStefano Zampini   PetscInt       i;
4589c0446d6SStefano Zampini   PetscErrorCode ierr;
4599c0446d6SStefano Zampini 
4609c0446d6SStefano Zampini   PetscFunctionBegin;
461da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
4629c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
4639c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
4649c0446d6SStefano Zampini   }
465d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
466da1bb401SStefano Zampini   /* allocate space then set */
4679c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
4689c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
469da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
470da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
4719c0446d6SStefano Zampini   }
4729c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
4739c0446d6SStefano Zampini   PetscFunctionReturn(0);
4749c0446d6SStefano Zampini }
4759c0446d6SStefano Zampini EXTERN_C_END
4769c0446d6SStefano Zampini #undef __FUNCT__
4779c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
4789c0446d6SStefano Zampini /*@
479da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
4809c0446d6SStefano Zampini 
4819c0446d6SStefano Zampini    Not collective
4829c0446d6SStefano Zampini 
4839c0446d6SStefano Zampini    Input Parameters:
4849c0446d6SStefano Zampini +  pc - the preconditioning context
485da1bb401SStefano Zampini -  n - number of index sets defining the fields
486da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
4879c0446d6SStefano Zampini 
4889c0446d6SStefano Zampini    Level: intermediate
4899c0446d6SStefano Zampini 
4909c0446d6SStefano Zampini    Notes:
4919c0446d6SStefano Zampini 
4929c0446d6SStefano Zampini .seealso: PCBDDC
4939c0446d6SStefano Zampini @*/
4949c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
4959c0446d6SStefano Zampini {
4969c0446d6SStefano Zampini   PetscErrorCode ierr;
4979c0446d6SStefano Zampini 
4989c0446d6SStefano Zampini   PetscFunctionBegin;
4999c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5009c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
5019c0446d6SStefano Zampini   PetscFunctionReturn(0);
5029c0446d6SStefano Zampini }
503da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
504534831adSStefano Zampini #undef __FUNCT__
505534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
506534831adSStefano Zampini /* -------------------------------------------------------------------------- */
507534831adSStefano Zampini /*
508534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
509534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
5109c0446d6SStefano Zampini 
511534831adSStefano Zampini    Input Parameter:
512534831adSStefano Zampini +  pc - the preconditioner contex
513534831adSStefano Zampini 
514534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
515534831adSStefano Zampini 
516534831adSStefano Zampini    Notes:
517534831adSStefano Zampini    The interface routine PCPreSolve() is not usually called directly by
518534831adSStefano Zampini    the user, but instead is called by KSPSolve().
519534831adSStefano Zampini */
520534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
521534831adSStefano Zampini {
522534831adSStefano Zampini   PetscErrorCode ierr;
523534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
524534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
525534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
526534831adSStefano Zampini   Mat            temp_mat;
5273972b0daSStefano Zampini   IS             dirIS;
5283972b0daSStefano Zampini   PetscInt       dirsize,i,*is_indices;
5293972b0daSStefano Zampini   PetscScalar    *array_x,*array_diagonal;
5303972b0daSStefano Zampini   Vec            used_vec;
5313972b0daSStefano Zampini   PetscBool      guess_nonzero;
532534831adSStefano Zampini 
533534831adSStefano Zampini   PetscFunctionBegin;
5343972b0daSStefano Zampini   if (x) {
5353972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
5363972b0daSStefano Zampini     used_vec = x;
5373972b0daSStefano Zampini   } else {
5383972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
5393972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
5403972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
5413972b0daSStefano Zampini   }
5423972b0daSStefano Zampini   /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */
5433972b0daSStefano Zampini   if (ksp) {
5443972b0daSStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr);
5453972b0daSStefano Zampini     if (!guess_nonzero) {
5463972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
5473972b0daSStefano Zampini     }
5483972b0daSStefano Zampini   }
5493972b0daSStefano Zampini   /* store the original rhs */
5503972b0daSStefano Zampini   ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
5513972b0daSStefano Zampini 
5523972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
5533972b0daSStefano Zampini   ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
5543972b0daSStefano Zampini   ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
5553972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5563972b0daSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5573972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5583972b0daSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5593972b0daSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr);
5603972b0daSStefano Zampini   if (dirIS) {
5613972b0daSStefano Zampini     ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr);
5623972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
5633972b0daSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
5643972b0daSStefano Zampini     ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5653972b0daSStefano Zampini     for (i=0;i<dirsize;i++) {
5663972b0daSStefano Zampini       array_x[is_indices[i]]=array_diagonal[is_indices[i]];
5673972b0daSStefano Zampini     }
5683972b0daSStefano Zampini     ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5693972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
5703972b0daSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
5713972b0daSStefano Zampini   }
5723972b0daSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5733972b0daSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
574b76ba322SStefano Zampini 
5753972b0daSStefano Zampini   /* remove the computed solution from the rhs */
5763972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
5773972b0daSStefano Zampini   ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr);
5783972b0daSStefano Zampini   ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
579b76ba322SStefano Zampini 
580b76ba322SStefano Zampini   /* store partially computed solution and set initial guess */
5813972b0daSStefano Zampini   if (x) {
5823972b0daSStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
5833972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
584b76ba322SStefano Zampini     if (pcbddc->use_exact_dirichlet) {
585b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
586b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
587b76ba322SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
588b76ba322SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
589b76ba322SStefano Zampini       ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
590b76ba322SStefano Zampini       if (ksp) {
591b76ba322SStefano Zampini         ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
592b76ba322SStefano Zampini       }
593b76ba322SStefano Zampini     }
5943972b0daSStefano Zampini   }
595b76ba322SStefano Zampini 
596b76ba322SStefano Zampini   /* rhs change of basis */
597b76ba322SStefano Zampini   if (pcbddc->usechangeofbasis) {
598b76ba322SStefano Zampini     /* swap pointers for local matrices */
599b76ba322SStefano Zampini     temp_mat = matis->A;
600b76ba322SStefano Zampini     matis->A = pcbddc->local_mat;
601b76ba322SStefano Zampini     pcbddc->local_mat = temp_mat;
602b76ba322SStefano Zampini     /* Get local rhs and apply transformation of basis */
603b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
604b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
605b76ba322SStefano Zampini     /* from original basis to modified basis */
606b76ba322SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
607b76ba322SStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
608b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
609b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6100bdf917eSStefano Zampini     if (ksp && pcbddc->NullSpace) {
6110bdf917eSStefano Zampini       ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec,PETSC_NULL);CHKERRQ(ierr);
6120bdf917eSStefano Zampini       ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs,PETSC_NULL);CHKERRQ(ierr);
613b76ba322SStefano Zampini     }
6140bdf917eSStefano Zampini   }
6150bdf917eSStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
616534831adSStefano Zampini   PetscFunctionReturn(0);
617534831adSStefano Zampini }
618534831adSStefano Zampini /* -------------------------------------------------------------------------- */
619534831adSStefano Zampini #undef __FUNCT__
620534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
621534831adSStefano Zampini /* -------------------------------------------------------------------------- */
622534831adSStefano Zampini /*
623534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
624534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
625534831adSStefano Zampini 
626534831adSStefano Zampini    Input Parameter:
627534831adSStefano Zampini +  pc - the preconditioner contex
628534831adSStefano Zampini 
629534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
630534831adSStefano Zampini 
631534831adSStefano Zampini    Notes:
632534831adSStefano Zampini    The interface routine PCPostSolve() is not usually called directly by
633534831adSStefano Zampini    the user, but instead is called by KSPSolve().
634534831adSStefano Zampini */
635534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
636534831adSStefano Zampini {
637534831adSStefano Zampini   PetscErrorCode ierr;
638534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
639534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
640534831adSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
641534831adSStefano Zampini   Mat            temp_mat;
642534831adSStefano Zampini 
643534831adSStefano Zampini   PetscFunctionBegin;
644534831adSStefano Zampini   if (pcbddc->usechangeofbasis) {
645534831adSStefano Zampini     /* swap pointers for local matrices */
646534831adSStefano Zampini     temp_mat = matis->A;
647534831adSStefano Zampini     matis->A = pcbddc->local_mat;
648534831adSStefano Zampini     pcbddc->local_mat = temp_mat;
649534831adSStefano Zampini     /* restore rhs to its original state */
6503425bc38SStefano Zampini     if (rhs) {
6513425bc38SStefano Zampini       ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
6523425bc38SStefano Zampini     }
653534831adSStefano Zampini     /* Get Local boundary and apply transformation of basis to solution vector */
654534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
655534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
656534831adSStefano Zampini     /* from modified basis to original basis */
657534831adSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
658534831adSStefano Zampini     /* put back modified values into the global vec using INSERT_VALUES copy mode */
659534831adSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
660534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
661534831adSStefano Zampini   }
6623972b0daSStefano Zampini   /* add solution removed in presolve */
6633425bc38SStefano Zampini   if (x) {
6643425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
6653425bc38SStefano Zampini   }
666534831adSStefano Zampini   PetscFunctionReturn(0);
667534831adSStefano Zampini }
668534831adSStefano Zampini /* -------------------------------------------------------------------------- */
66953cdbc3dSStefano Zampini #undef __FUNCT__
67053cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
6710c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6720c7d97c5SJed Brown /*
6730c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
6740c7d97c5SJed Brown                   by setting data structures and options.
6750c7d97c5SJed Brown 
6760c7d97c5SJed Brown    Input Parameter:
67753cdbc3dSStefano Zampini +  pc - the preconditioner context
6780c7d97c5SJed Brown 
6790c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
6800c7d97c5SJed Brown 
6810c7d97c5SJed Brown    Notes:
6820c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
6830c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
6840c7d97c5SJed Brown */
68553cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
6860c7d97c5SJed Brown {
6870c7d97c5SJed Brown   PetscErrorCode ierr;
6880c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
6890c7d97c5SJed Brown 
6900c7d97c5SJed Brown   PetscFunctionBegin;
6910c7d97c5SJed Brown   if (!pc->setupcalled) {
6923b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
6939c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
6940c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
6950c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
6960c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
6970c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
6980bdf917eSStefano Zampini 
6990c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
7003b03a366Sstefano_zampini     /* Get stdout for dbg */
701e269702eSStefano Zampini     if (pcbddc->dbg_flag) {
702e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
703e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
704e269702eSStefano Zampini     }
7053b03a366Sstefano_zampini     /* Analyze local interface */
7060c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
7073b03a366Sstefano_zampini     /* Set up local constraint matrix */
7083b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
7090c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
7100c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
7110c7d97c5SJed Brown   }
7120c7d97c5SJed Brown   PetscFunctionReturn(0);
7130c7d97c5SJed Brown }
7140c7d97c5SJed Brown 
7150c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7160c7d97c5SJed Brown /*
7170c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
7180c7d97c5SJed Brown 
7190c7d97c5SJed Brown    Input Parameters:
7200c7d97c5SJed Brown .  pc - the preconditioner context
7210c7d97c5SJed Brown .  r - input vector (global)
7220c7d97c5SJed Brown 
7230c7d97c5SJed Brown    Output Parameter:
7240c7d97c5SJed Brown .  z - output vector (global)
7250c7d97c5SJed Brown 
7260c7d97c5SJed Brown    Application Interface Routine: PCApply()
7270c7d97c5SJed Brown  */
7280c7d97c5SJed Brown #undef __FUNCT__
7290c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
73053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
7310c7d97c5SJed Brown {
7320c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
7330c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
7340c7d97c5SJed Brown   PetscErrorCode    ierr;
7353b03a366Sstefano_zampini   const PetscScalar one = 1.0;
7363b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
7372617d88aSStefano Zampini   const PetscScalar zero = 0.0;
7380c7d97c5SJed Brown 
7390c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
7400c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
74129622bf0SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->inexact_prec_type = PETSC_TRUE) */
7420c7d97c5SJed Brown 
7430c7d97c5SJed Brown   PetscFunctionBegin;
744b76ba322SStefano Zampini   if (!pcbddc->use_exact_dirichlet) {
7450c7d97c5SJed Brown     /* First Dirichlet solve */
7460c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7470c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
74853cdbc3dSStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
7490c7d97c5SJed Brown     /*
7500c7d97c5SJed Brown       Assembling right hand side for BDDC operator
7510c7d97c5SJed Brown       - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
7520c7d97c5SJed Brown       - the interface part of the global vector z
7530c7d97c5SJed Brown     */
7540c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
7550c7d97c5SJed Brown     ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
75629622bf0SStefano Zampini     if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
7570c7d97c5SJed Brown     ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
7580c7d97c5SJed Brown     ierr = VecCopy(r,z);CHKERRQ(ierr);
7590c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7600c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7612617d88aSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7622617d88aSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
763b76ba322SStefano Zampini   } else {
764b76ba322SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
765b76ba322SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7660bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
767b76ba322SStefano Zampini     ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr);
768b76ba322SStefano Zampini   }
769b76ba322SStefano Zampini 
770b76ba322SStefano Zampini   /* Apply partition of unity */
7712617d88aSStefano Zampini   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
7722617d88aSStefano Zampini 
7732617d88aSStefano Zampini   /* Apply interface preconditioner
7742617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
7752617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
7762617d88aSStefano Zampini 
7772617d88aSStefano Zampini   /* Apply partition of unity and sum boundary values */
7782617d88aSStefano Zampini   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
7792617d88aSStefano Zampini   ierr = VecSet(z,zero);CHKERRQ(ierr);
7802617d88aSStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7812617d88aSStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7820c7d97c5SJed Brown 
7833b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
7840c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7850c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7860c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
78729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
78853cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
7890c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
79029622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
7910c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
7920c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7930c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7940c7d97c5SJed Brown   PetscFunctionReturn(0);
7950c7d97c5SJed Brown 
7960c7d97c5SJed Brown }
797da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
798da1bb401SStefano Zampini #undef __FUNCT__
799da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
800da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
801da1bb401SStefano Zampini {
802da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
8030bdf917eSStefano Zampini   PetscInt       i;
804da1bb401SStefano Zampini   PetscErrorCode ierr;
805da1bb401SStefano Zampini 
806da1bb401SStefano Zampini   PetscFunctionBegin;
807da1bb401SStefano Zampini   /* free data created by PCIS */
808da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
809da1bb401SStefano Zampini   /* free BDDC data  */
8100bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->CoarseNullSpace);CHKERRQ(ierr);
8110bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
8123972b0daSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
813534831adSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
814534831adSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
815534831adSStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
816da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
817da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
818da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
819da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
820da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
821da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
822da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
823da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
824da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
825da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
826da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
827da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
828da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
829da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
830da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
831da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
832da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
833da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
834da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
835da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
836da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
837da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
838da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
8390bdf917eSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
840da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
841da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
842da1bb401SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
843da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
844da1bb401SStefano Zampini   for (i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
845da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
846da1bb401SStefano Zampini   for (i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
847da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
848da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
8493972b0daSStefano Zampini   /* Free graph structure */
850da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->xadj);CHKERRQ(ierr);
851da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->adjncy);CHKERRQ(ierr);
852142dfd88SStefano Zampini   if (pcbddc->mat_graph->nvtxs) {
853da1bb401SStefano Zampini     ierr = PetscFree(pcbddc->mat_graph->neighbours_set[0]);CHKERRQ(ierr);
854142dfd88SStefano Zampini   }
855da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->neighbours_set);CHKERRQ(ierr);
8563972b0daSStefano Zampini   ierr = PetscFree4(pcbddc->mat_graph->where,pcbddc->mat_graph->count,pcbddc->mat_graph->cptr,pcbddc->mat_graph->queue);CHKERRQ(ierr);
8573972b0daSStefano Zampini   ierr = PetscFree2(pcbddc->mat_graph->which_dof,pcbddc->mat_graph->touched);CHKERRQ(ierr);
8583972b0daSStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->where_ncmps);CHKERRQ(ierr);
859da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
8603425bc38SStefano Zampini   /* remove functions */
8614fad6a16SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseningRatio_C","",PETSC_NULL);CHKERRQ(ierr);
8624fad6a16SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetMaxLevels_C","",PETSC_NULL);CHKERRQ(ierr);
8630bdf917eSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNullSpace_C","",PETSC_NULL);CHKERRQ(ierr);
8643425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","",PETSC_NULL);CHKERRQ(ierr);
8653425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","",PETSC_NULL);CHKERRQ(ierr);
8663425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C","",PETSC_NULL);CHKERRQ(ierr);
8673425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","",PETSC_NULL);CHKERRQ(ierr);
8683425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","",PETSC_NULL);CHKERRQ(ierr);
8693425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","",PETSC_NULL);CHKERRQ(ierr);
8703425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C","",PETSC_NULL);CHKERRQ(ierr);
8713425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPreSolve_C","",PETSC_NULL);CHKERRQ(ierr);
8723425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPostSolve_C","",PETSC_NULL);CHKERRQ(ierr);
8733425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C","",PETSC_NULL);CHKERRQ(ierr);
8743425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C","",PETSC_NULL);CHKERRQ(ierr);
8753425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C","",PETSC_NULL);CHKERRQ(ierr);
876da1bb401SStefano Zampini   /* Free the private data structure that was hanging off the PC */
877da1bb401SStefano Zampini   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
878da1bb401SStefano Zampini   PetscFunctionReturn(0);
879da1bb401SStefano Zampini }
8803425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
8813425bc38SStefano Zampini EXTERN_C_BEGIN
8823425bc38SStefano Zampini #undef __FUNCT__
8833425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
8843425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
8853425bc38SStefano Zampini {
8863425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
8873425bc38SStefano Zampini   PC_IS*         pcis;
8883425bc38SStefano Zampini   PC_BDDC*       pcbddc;
8893425bc38SStefano Zampini   PetscErrorCode ierr;
8900c7d97c5SJed Brown 
8913425bc38SStefano Zampini   PetscFunctionBegin;
8923425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
8933425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
8943425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
8953425bc38SStefano Zampini 
8963425bc38SStefano Zampini   /* change of basis for physical rhs if needed
8973425bc38SStefano Zampini      It also changes the rhs in case of dirichlet boundaries */
8983425bc38SStefano Zampini   (*mat_ctx->pc->ops->presolve)(mat_ctx->pc,PETSC_NULL,standard_rhs,PETSC_NULL);
8993425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
9003425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9013425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9023425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9033425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9043425bc38SStefano Zampini   /* scale rhs since it should be unassembled */
9053425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
90629622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9073425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
9083425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9093425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
9103425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
9113425bc38SStefano Zampini     ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr);
9123425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9133425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9143425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9153425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9163425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
9173425bc38SStefano Zampini   }
9183425bc38SStefano Zampini   /* BDDC rhs */
9193425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
92029622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9213425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9223425bc38SStefano Zampini   }
9233425bc38SStefano Zampini   /* apply BDDC */
9243425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9253425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
9263425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
9273425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
9283425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9293425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9303425bc38SStefano Zampini   /* restore original rhs */
9313425bc38SStefano Zampini   ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr);
9323425bc38SStefano Zampini   PetscFunctionReturn(0);
9333425bc38SStefano Zampini }
9343425bc38SStefano Zampini EXTERN_C_END
9353425bc38SStefano Zampini #undef __FUNCT__
9363425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
9373425bc38SStefano Zampini /*@
9383425bc38SStefano Zampini  PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system.
9393425bc38SStefano Zampini 
9403425bc38SStefano Zampini    Collective
9413425bc38SStefano Zampini 
9423425bc38SStefano Zampini    Input Parameters:
9433425bc38SStefano Zampini +  fetidp_mat   - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
9443425bc38SStefano Zampini +  standard_rhs - the rhs of your linear system
9453425bc38SStefano Zampini 
9463425bc38SStefano Zampini    Output Parameters:
9473425bc38SStefano Zampini +  fetidp_flux_rhs   - the rhs of the FETIDP linear system
9483425bc38SStefano Zampini 
9493425bc38SStefano Zampini    Level: developer
9503425bc38SStefano Zampini 
9513425bc38SStefano Zampini    Notes:
9523425bc38SStefano Zampini 
9533425bc38SStefano Zampini .seealso: PCBDDC
9543425bc38SStefano Zampini @*/
9553425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
9563425bc38SStefano Zampini {
9573425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
9583425bc38SStefano Zampini   PetscErrorCode ierr;
9593425bc38SStefano Zampini 
9603425bc38SStefano Zampini   PetscFunctionBegin;
9613425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9623425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
9633425bc38SStefano Zampini   PetscFunctionReturn(0);
9643425bc38SStefano Zampini }
9653425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
9663425bc38SStefano Zampini EXTERN_C_BEGIN
9673425bc38SStefano Zampini #undef __FUNCT__
9683425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
9693425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
9703425bc38SStefano Zampini {
9713425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
9723425bc38SStefano Zampini   PC_IS*         pcis;
9733425bc38SStefano Zampini   PC_BDDC*       pcbddc;
9743425bc38SStefano Zampini   PetscErrorCode ierr;
9753425bc38SStefano Zampini 
9763425bc38SStefano Zampini   PetscFunctionBegin;
9773425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
9783425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
9793425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
9803425bc38SStefano Zampini 
9813425bc38SStefano Zampini   /* apply B_delta^T */
9823425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9833425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9843425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
9853425bc38SStefano Zampini   /* compute rhs for BDDC application */
9863425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
98729622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
9883425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
9893425bc38SStefano Zampini   }
9903425bc38SStefano Zampini   /* apply BDDC */
9913425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
9923425bc38SStefano Zampini   /* put values into standard global vector */
9933425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9943425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
99529622bf0SStefano Zampini   if (!pcbddc->inexact_prec_type) {
9963425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
9973425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
9983425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
9993425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
10003425bc38SStefano Zampini   }
10013425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10023425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10033425bc38SStefano Zampini   /* final change of basis if needed
10043425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
10053425bc38SStefano Zampini   (*mat_ctx->pc->ops->postsolve)(mat_ctx->pc,PETSC_NULL,PETSC_NULL,standard_sol);
10063425bc38SStefano Zampini   PetscFunctionReturn(0);
10073425bc38SStefano Zampini 
10083425bc38SStefano Zampini }
10093425bc38SStefano Zampini EXTERN_C_END
10103425bc38SStefano Zampini #undef __FUNCT__
10113425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
10123425bc38SStefano Zampini /*@
10133425bc38SStefano Zampini  PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system.
10143425bc38SStefano Zampini 
10153425bc38SStefano Zampini    Collective
10163425bc38SStefano Zampini 
10173425bc38SStefano Zampini    Input Parameters:
10183425bc38SStefano Zampini +  fetidp_mat        - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators
10193425bc38SStefano Zampini +  fetidp_flux_sol - the solution of the FETIDP linear system
10203425bc38SStefano Zampini 
10213425bc38SStefano Zampini    Output Parameters:
10223425bc38SStefano Zampini +  standard_sol      - the solution on the global domain
10233425bc38SStefano Zampini 
10243425bc38SStefano Zampini    Level: developer
10253425bc38SStefano Zampini 
10263425bc38SStefano Zampini    Notes:
10273425bc38SStefano Zampini 
10283425bc38SStefano Zampini .seealso: PCBDDC
10293425bc38SStefano Zampini @*/
10303425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
10313425bc38SStefano Zampini {
10323425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
10333425bc38SStefano Zampini   PetscErrorCode ierr;
10343425bc38SStefano Zampini 
10353425bc38SStefano Zampini   PetscFunctionBegin;
10363425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
10373425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
10383425bc38SStefano Zampini   PetscFunctionReturn(0);
10393425bc38SStefano Zampini }
10403425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
10413425bc38SStefano Zampini EXTERN_C_BEGIN
1042f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
1043f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
1044f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
1045f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
10463425bc38SStefano Zampini #undef __FUNCT__
10473425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
10483425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
10493425bc38SStefano Zampini {
10503425bc38SStefano Zampini   FETIDPMat_ctx  *fetidpmat_ctx;
10513425bc38SStefano Zampini   Mat            newmat;
10523425bc38SStefano Zampini   FETIDPPC_ctx  *fetidppc_ctx;
10533425bc38SStefano Zampini   PC             newpc;
10543425bc38SStefano Zampini   MPI_Comm       comm = ((PetscObject)pc)->comm;
10553425bc38SStefano Zampini   PetscErrorCode ierr;
10563425bc38SStefano Zampini 
10573425bc38SStefano Zampini   PetscFunctionBegin;
10583425bc38SStefano Zampini   /* FETIDP linear matrix */
10593425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx);CHKERRQ(ierr);
10603425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
10613425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
10623425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
10633425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
10643425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
10653425bc38SStefano Zampini   /* FETIDP preconditioner */
10663425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx);CHKERRQ(ierr);
10673425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
10683425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
10693425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
10703425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
10713425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
10723425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
10733425bc38SStefano Zampini   ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr);
10743425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
10753425bc38SStefano Zampini   /* return pointers for objects created */
10763425bc38SStefano Zampini   *fetidp_mat=newmat;
10773425bc38SStefano Zampini   *fetidp_pc=newpc;
10783425bc38SStefano Zampini   PetscFunctionReturn(0);
10793425bc38SStefano Zampini }
10803425bc38SStefano Zampini EXTERN_C_END
10813425bc38SStefano Zampini #undef __FUNCT__
10823425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
10833425bc38SStefano Zampini /*@
10843425bc38SStefano Zampini  PCBDDCCreateFETIDPOperators - Create operators for FETIDP.
10853425bc38SStefano Zampini 
10863425bc38SStefano Zampini    Collective
10873425bc38SStefano Zampini 
10883425bc38SStefano Zampini    Input Parameters:
10893425bc38SStefano Zampini +  pc - the BDDC preconditioning context (setup must be already called)
10903425bc38SStefano Zampini 
10913425bc38SStefano Zampini    Level: developer
10923425bc38SStefano Zampini 
10933425bc38SStefano Zampini    Notes:
10943425bc38SStefano Zampini 
10953425bc38SStefano Zampini .seealso: PCBDDC
10963425bc38SStefano Zampini @*/
10973425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
10983425bc38SStefano Zampini {
10993425bc38SStefano Zampini   PetscErrorCode ierr;
11003425bc38SStefano Zampini 
11013425bc38SStefano Zampini   PetscFunctionBegin;
11023425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11033425bc38SStefano Zampini   if (pc->setupcalled) {
11043425bc38SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
1105f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
11063425bc38SStefano Zampini   PetscFunctionReturn(0);
11073425bc38SStefano Zampini }
11080c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1109da1bb401SStefano Zampini /*MC
1110da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
11110c7d97c5SJed Brown 
1112da1bb401SStefano Zampini    Options Database Keys:
1113da1bb401SStefano Zampini .    -pcbddc ??? -
1114da1bb401SStefano Zampini 
1115da1bb401SStefano Zampini    Level: intermediate
1116da1bb401SStefano Zampini 
1117da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
1118da1bb401SStefano Zampini 
1119da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
1120da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
1121da1bb401SStefano Zampini           on the subdomains).
1122da1bb401SStefano Zampini 
1123da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
1124da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
1125da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
1126da1bb401SStefano Zampini 
1127da1bb401SStefano Zampini    Contributed by Stefano Zampini
1128da1bb401SStefano Zampini 
1129da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
1130da1bb401SStefano Zampini M*/
1131da1bb401SStefano Zampini EXTERN_C_BEGIN
1132da1bb401SStefano Zampini #undef __FUNCT__
1133da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
1134da1bb401SStefano Zampini PetscErrorCode PCCreate_BDDC(PC pc)
1135da1bb401SStefano Zampini {
1136da1bb401SStefano Zampini   PetscErrorCode ierr;
1137da1bb401SStefano Zampini   PC_BDDC        *pcbddc;
1138da1bb401SStefano Zampini   PCBDDCGraph    mat_graph;
1139da1bb401SStefano Zampini 
1140da1bb401SStefano Zampini   PetscFunctionBegin;
1141da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
1142da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
1143da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
1144da1bb401SStefano Zampini 
1145da1bb401SStefano Zampini   /* create PCIS data structure */
1146da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
1147da1bb401SStefano Zampini 
1148da1bb401SStefano Zampini   /* BDDC specific */
11490bdf917eSStefano Zampini   pcbddc->CoarseNullSpace            = 0;
11500bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
11513972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
1152534831adSStefano Zampini   pcbddc->original_rhs               = 0;
1153534831adSStefano Zampini   pcbddc->local_mat                  = 0;
1154534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
1155534831adSStefano Zampini   pcbddc->usechangeofbasis           = PETSC_TRUE;
1156534831adSStefano Zampini   pcbddc->usechangeonfaces           = PETSC_FALSE;
1157da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
1158da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
1159da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
1160da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
1161da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
1162da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
1163da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
1164da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
1165da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
1166da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
1167da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
1168da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
1169da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
1170da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
1171da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
117229622bf0SStefano Zampini   pcbddc->inexact_prec_type          = PETSC_FALSE;
1173da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
1174da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
1175da1bb401SStefano Zampini   pcbddc->ISForVertices              = 0;
1176da1bb401SStefano Zampini   pcbddc->n_ISForFaces               = 0;
1177da1bb401SStefano Zampini   pcbddc->n_ISForEdges               = 0;
1178da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
1179da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
1180da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
1181da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
1182da1bb401SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
1183da1bb401SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
1184da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
1185da1bb401SStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
1186da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
1187b76ba322SStefano Zampini   pcbddc->use_exact_dirichlet        = PETSC_TRUE;
11884fad6a16SStefano Zampini   pcbddc->current_level              = 0;
11894fad6a16SStefano Zampini   pcbddc->max_levels                 = 1;
1190da1bb401SStefano Zampini 
1191da1bb401SStefano Zampini   /* allocate and initialize needed graph structure */
1192da1bb401SStefano Zampini   ierr = PetscMalloc(sizeof(*mat_graph),&pcbddc->mat_graph);CHKERRQ(ierr);
1193da1bb401SStefano Zampini   pcbddc->mat_graph->xadj            = 0;
1194da1bb401SStefano Zampini   pcbddc->mat_graph->adjncy          = 0;
1195da1bb401SStefano Zampini 
1196da1bb401SStefano Zampini   /* function pointers */
1197da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
1198da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
1199da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
1200da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
1201da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
1202da1bb401SStefano Zampini   pc->ops->view                = 0;
1203da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
1204da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
1205da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
1206534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
1207534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
1208da1bb401SStefano Zampini 
1209da1bb401SStefano Zampini   /* composing function */
12104fad6a16SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseningRatio_C","PCBDDCSetCoarseningRatio_BDDC",
12114fad6a16SStefano Zampini                     PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
12124fad6a16SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetMaxLevels_C","PCBDDCSetMaxLevels_BDDC",
12134fad6a16SStefano Zampini                     PCBDDCSetMaxLevels_BDDC);CHKERRQ(ierr);
12140bdf917eSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNullSpace_C","PCBDDCSetNullSpace_BDDC",
12150bdf917eSStefano Zampini                     PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
1216da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
1217da1bb401SStefano Zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1218da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
1219da1bb401SStefano Zampini                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1220da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C","PCBDDCGetDirichletBoundaries_BDDC",
1221da1bb401SStefano Zampini                     PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
1222da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
1223da1bb401SStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
1224da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
1225da1bb401SStefano Zampini                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
1226da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
1227da1bb401SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
1228da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C","PCBDDCSetLocalAdjacencyGraph_BDDC",
1229da1bb401SStefano Zampini                     PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
1230534831adSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPreSolve_C","PCPreSolve_BDDC",
1231534831adSStefano Zampini                     PCPreSolve_BDDC);CHKERRQ(ierr);
1232534831adSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCPostSolve_C","PCPostSolve_BDDC",
1233534831adSStefano Zampini                     PCPostSolve_BDDC);CHKERRQ(ierr);
12343425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C","PCBDDCCreateFETIDPOperators_BDDC",
12353425bc38SStefano Zampini                     PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
12363425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C","PCBDDCMatFETIDPGetRHS_BDDC",
12373425bc38SStefano Zampini                     PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
12383425bc38SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C","PCBDDCMatFETIDPGetSolution_BDDC",
12393425bc38SStefano Zampini                     PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
1240da1bb401SStefano Zampini   PetscFunctionReturn(0);
1241da1bb401SStefano Zampini }
1242da1bb401SStefano Zampini EXTERN_C_END
12433425bc38SStefano Zampini 
1244da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1245da1bb401SStefano Zampini /* All static functions from now on                                           */
1246da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
12474fad6a16SStefano Zampini #undef __FUNCT__
124829622bf0SStefano Zampini #define __FUNCT__ "PCBDDCApplyNullSpaceCorrectionPC"
124929622bf0SStefano Zampini static PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC pc,Vec x,Vec y)
125029622bf0SStefano Zampini {
125129622bf0SStefano Zampini   NullSpaceCorrection_ctx *pc_ctx;
125229622bf0SStefano Zampini   PetscErrorCode          ierr;
125329622bf0SStefano Zampini 
125429622bf0SStefano Zampini   PetscFunctionBegin;
125529622bf0SStefano Zampini   ierr = PCShellGetContext(pc,(void**)&pc_ctx);CHKERRQ(ierr);
125629622bf0SStefano Zampini   /* E */
125729622bf0SStefano Zampini   ierr = MatMultTranspose(pc_ctx->Lbasis_mat,x,pc_ctx->work_small_2);CHKERRQ(ierr);
125829622bf0SStefano Zampini   ierr = MatMultAdd(pc_ctx->Kbasis_mat,pc_ctx->work_small_2,x,pc_ctx->work_full_1);CHKERRQ(ierr);
125929622bf0SStefano Zampini   /* P^-1 */
126029622bf0SStefano Zampini   ierr = PCApply(pc_ctx->local_pc,pc_ctx->work_full_1,pc_ctx->work_full_2);CHKERRQ(ierr);
126129622bf0SStefano Zampini   /* E^T */
126229622bf0SStefano Zampini   ierr = MatMultTranspose(pc_ctx->Kbasis_mat,pc_ctx->work_full_2,pc_ctx->work_small_1);CHKERRQ(ierr);
126329622bf0SStefano Zampini   ierr = VecScale(pc_ctx->work_small_1,-1.0);CHKERRQ(ierr);
126429622bf0SStefano Zampini   ierr = MatMultAdd(pc_ctx->Lbasis_mat,pc_ctx->work_small_1,pc_ctx->work_full_2,pc_ctx->work_full_1);CHKERRQ(ierr);
126529622bf0SStefano Zampini   /* Sum contributions */
126629622bf0SStefano Zampini   ierr = MatMultAdd(pc_ctx->basis_mat,pc_ctx->work_small_2,pc_ctx->work_full_1,y);CHKERRQ(ierr);
126729622bf0SStefano Zampini   PetscFunctionReturn(0);
126829622bf0SStefano Zampini }
126929622bf0SStefano Zampini 
127029622bf0SStefano Zampini #undef __FUNCT__
127129622bf0SStefano Zampini #define __FUNCT__ "PCBDDCDestroyNullSpaceCorrectionPC"
127229622bf0SStefano Zampini static PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC pc)
127329622bf0SStefano Zampini {
127429622bf0SStefano Zampini   NullSpaceCorrection_ctx *pc_ctx;
127529622bf0SStefano Zampini   PetscErrorCode          ierr;
127629622bf0SStefano Zampini 
127729622bf0SStefano Zampini   PetscFunctionBegin;
127829622bf0SStefano Zampini   ierr = PCShellGetContext(pc,(void**)&pc_ctx);CHKERRQ(ierr);
127929622bf0SStefano Zampini   ierr = VecDestroy(&pc_ctx->work_small_1);CHKERRQ(ierr);
128029622bf0SStefano Zampini   ierr = VecDestroy(&pc_ctx->work_small_2);CHKERRQ(ierr);
128129622bf0SStefano Zampini   ierr = VecDestroy(&pc_ctx->work_full_1);CHKERRQ(ierr);
128229622bf0SStefano Zampini   ierr = VecDestroy(&pc_ctx->work_full_2);CHKERRQ(ierr);
128329622bf0SStefano Zampini   ierr = MatDestroy(&pc_ctx->basis_mat);CHKERRQ(ierr);
128429622bf0SStefano Zampini   ierr = MatDestroy(&pc_ctx->Lbasis_mat);CHKERRQ(ierr);
128529622bf0SStefano Zampini   ierr = MatDestroy(&pc_ctx->Kbasis_mat);CHKERRQ(ierr);
128629622bf0SStefano Zampini   ierr = PCDestroy(&pc_ctx->local_pc);CHKERRQ(ierr);
128729622bf0SStefano Zampini   ierr = PetscFree(pc_ctx);CHKERRQ(ierr);
128829622bf0SStefano Zampini   PetscFunctionReturn(0);
128929622bf0SStefano Zampini }
129029622bf0SStefano Zampini 
129129622bf0SStefano Zampini #undef __FUNCT__
129229622bf0SStefano Zampini #define __FUNCT__ "PCBDDCAdaptLocalProblem"
129329622bf0SStefano Zampini static PetscErrorCode PCBDDCAdaptLocalProblem(PC pc,IS local_dofs)
129429622bf0SStefano Zampini {
1295f23aa3ddSBarry Smith   extern PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC,Vec,Vec);
1296f23aa3ddSBarry Smith   extern PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC);
129729622bf0SStefano Zampini 
129829622bf0SStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
129929622bf0SStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
130029622bf0SStefano Zampini   Mat_IS*                 matis = (Mat_IS*)pc->pmat->data;
130129622bf0SStefano Zampini   KSP                     *local_ksp;
130229622bf0SStefano Zampini   PC                      newpc;
130329622bf0SStefano Zampini   NullSpaceCorrection_ctx *shell_ctx;
130429622bf0SStefano Zampini   Mat                     local_mat,local_pmat,small_mat,inv_small_mat;
130529622bf0SStefano Zampini   MatStructure            local_mat_struct;
130629622bf0SStefano Zampini   Vec                     work1,work2,work3;
130729622bf0SStefano Zampini   const Vec               *nullvecs;
130829622bf0SStefano Zampini   VecScatter              scatter_ctx;
130929622bf0SStefano Zampini   IS                      is_aux;
131029622bf0SStefano Zampini   MatFactorInfo           matinfo;
131129622bf0SStefano Zampini   PetscScalar             *basis_mat,*Kbasis_mat,*array,*array_mat;
131229622bf0SStefano Zampini   PetscScalar             one = 1.0,zero = 0.0, m_one = -1.0;
131329622bf0SStefano Zampini   PetscInt                basis_dofs,basis_size,nnsp_size,i,k,n_I,n_R;
131429622bf0SStefano Zampini   PetscBool               nnsp_has_cnst;
131529622bf0SStefano Zampini   PetscErrorCode          ierr;
131629622bf0SStefano Zampini 
131729622bf0SStefano Zampini   PetscFunctionBegin;
131829622bf0SStefano Zampini   /* Infer the local solver */
131929622bf0SStefano Zampini   ierr = ISGetSize(local_dofs,&basis_dofs);CHKERRQ(ierr);
132029622bf0SStefano Zampini   ierr = VecGetSize(pcis->vec1_D,&n_I);CHKERRQ(ierr);
132129622bf0SStefano Zampini   ierr = VecGetSize(pcbddc->vec1_R,&n_R);CHKERRQ(ierr);
132229622bf0SStefano Zampini   if (basis_dofs == n_I) {
132329622bf0SStefano Zampini     /* Dirichlet solver */
132429622bf0SStefano Zampini     local_ksp = &pcbddc->ksp_D;
132529622bf0SStefano Zampini   } else if (basis_dofs == n_R) {
132629622bf0SStefano Zampini     /* Neumann solver */
132729622bf0SStefano Zampini     local_ksp = &pcbddc->ksp_R;
1328f23aa3ddSBarry Smith   } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in %s: unknown local IS size %d. n_I=%d, n_R=%d)\n",basis_dofs,n_I,n_R);
132929622bf0SStefano Zampini   ierr = KSPGetOperators(*local_ksp,&local_mat,&local_pmat,&local_mat_struct);CHKERRQ(ierr);
133029622bf0SStefano Zampini 
133129622bf0SStefano Zampini   /* Get null space vecs */
133229622bf0SStefano Zampini   ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nnsp_has_cnst,&nnsp_size,&nullvecs);CHKERRQ(ierr);
133329622bf0SStefano Zampini   basis_size = nnsp_size;
133429622bf0SStefano Zampini   if (nnsp_has_cnst) {
133529622bf0SStefano Zampini     basis_size++;
133629622bf0SStefano Zampini   }
133729622bf0SStefano Zampini 
133829622bf0SStefano Zampini   /* Create shell ctx */
133929622bf0SStefano Zampini   ierr = PetscMalloc(sizeof(*shell_ctx),&shell_ctx);CHKERRQ(ierr);
134029622bf0SStefano Zampini 
134129622bf0SStefano Zampini   /* Create work vectors in shell context */
134229622bf0SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&shell_ctx->work_small_1);CHKERRQ(ierr);
134329622bf0SStefano Zampini   ierr = VecSetSizes(shell_ctx->work_small_1,basis_size,basis_size);CHKERRQ(ierr);
134429622bf0SStefano Zampini   ierr = VecSetType(shell_ctx->work_small_1,VECSEQ);CHKERRQ(ierr);
134529622bf0SStefano Zampini   ierr = VecDuplicate(shell_ctx->work_small_1,&shell_ctx->work_small_2);CHKERRQ(ierr);
134629622bf0SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&shell_ctx->work_full_1);CHKERRQ(ierr);
134729622bf0SStefano Zampini   ierr = VecSetSizes(shell_ctx->work_full_1,basis_dofs,basis_dofs);CHKERRQ(ierr);
134829622bf0SStefano Zampini   ierr = VecSetType(shell_ctx->work_full_1,VECSEQ);CHKERRQ(ierr);
134929622bf0SStefano Zampini   ierr = VecDuplicate(shell_ctx->work_full_1,&shell_ctx->work_full_2);CHKERRQ(ierr);
135029622bf0SStefano Zampini 
135129622bf0SStefano Zampini   /* Allocate workspace */
135229622bf0SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,PETSC_NULL,&shell_ctx->basis_mat);CHKERRQ(ierr);
135329622bf0SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,PETSC_NULL,&shell_ctx->Kbasis_mat);CHKERRQ(ierr);
135429622bf0SStefano Zampini   ierr = MatDenseGetArray(shell_ctx->basis_mat,&basis_mat);CHKERRQ(ierr);
135529622bf0SStefano Zampini   ierr = MatDenseGetArray(shell_ctx->Kbasis_mat,&Kbasis_mat);CHKERRQ(ierr);
135629622bf0SStefano Zampini 
135729622bf0SStefano Zampini   /* Restrict local null space on selected dofs (Dirichlet or Neumann)
135829622bf0SStefano Zampini      and compute matrices N and K*N */
135929622bf0SStefano Zampini   ierr = VecDuplicate(shell_ctx->work_full_1,&work1);CHKERRQ(ierr);
136029622bf0SStefano Zampini   ierr = VecDuplicate(shell_ctx->work_full_1,&work2);CHKERRQ(ierr);
136129622bf0SStefano Zampini   ierr = VecScatterCreate(pcis->vec1_N,local_dofs,work1,(IS)0,&scatter_ctx);CHKERRQ(ierr);
136229622bf0SStefano Zampini   k=0;
136329622bf0SStefano Zampini   for (;k<nnsp_size;k++) {
136429622bf0SStefano Zampini     ierr = VecScatterBegin(matis->ctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
136529622bf0SStefano Zampini     ierr = VecScatterEnd(matis->ctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
136629622bf0SStefano Zampini     ierr = VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);CHKERRQ(ierr);
136729622bf0SStefano Zampini     ierr = VecScatterBegin(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
136829622bf0SStefano Zampini     ierr = VecScatterEnd(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
136929622bf0SStefano Zampini     ierr = VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);CHKERRQ(ierr);
137029622bf0SStefano Zampini     ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
137129622bf0SStefano Zampini     ierr = VecResetArray(work1);CHKERRQ(ierr);
137229622bf0SStefano Zampini     ierr = VecResetArray(work2);CHKERRQ(ierr);
137329622bf0SStefano Zampini   }
137429622bf0SStefano Zampini   if (nnsp_has_cnst) {
137529622bf0SStefano Zampini     ierr = VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);CHKERRQ(ierr);
137629622bf0SStefano Zampini     ierr = VecSet(work1,one);CHKERRQ(ierr);
137729622bf0SStefano Zampini     ierr = VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);CHKERRQ(ierr);
137829622bf0SStefano Zampini     ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
137929622bf0SStefano Zampini     ierr = VecResetArray(work1);CHKERRQ(ierr);
138029622bf0SStefano Zampini     ierr = VecResetArray(work2);CHKERRQ(ierr);
138129622bf0SStefano Zampini   }
138229622bf0SStefano Zampini   ierr = VecDestroy(&work1);CHKERRQ(ierr);
138329622bf0SStefano Zampini   ierr = VecDestroy(&work2);CHKERRQ(ierr);
138429622bf0SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
138529622bf0SStefano Zampini   ierr = MatDenseRestoreArray(shell_ctx->basis_mat,&basis_mat);CHKERRQ(ierr);
138629622bf0SStefano Zampini   ierr = MatDenseRestoreArray(shell_ctx->Kbasis_mat,&Kbasis_mat);CHKERRQ(ierr);
138729622bf0SStefano Zampini 
138829622bf0SStefano Zampini   /* Assemble another Mat object in shell context */
138929622bf0SStefano Zampini   ierr = MatTransposeMatMult(shell_ctx->basis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&small_mat);CHKERRQ(ierr);
139029622bf0SStefano Zampini   ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
139129622bf0SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,basis_size,0,1,&is_aux);CHKERRQ(ierr);
139229622bf0SStefano Zampini   ierr = MatLUFactor(small_mat,is_aux,is_aux,&matinfo);CHKERRQ(ierr);
139329622bf0SStefano Zampini   ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
139429622bf0SStefano Zampini   ierr = PetscMalloc(basis_size*basis_size*sizeof(PetscScalar),&array_mat);CHKERRQ(ierr);
139529622bf0SStefano Zampini   for (k=0;k<basis_size;k++) {
139629622bf0SStefano Zampini     ierr = VecSet(shell_ctx->work_small_1,zero);CHKERRQ(ierr);
139729622bf0SStefano Zampini     ierr = VecSetValue(shell_ctx->work_small_1,k,one,INSERT_VALUES);CHKERRQ(ierr);
139829622bf0SStefano Zampini     ierr = VecAssemblyBegin(shell_ctx->work_small_1);CHKERRQ(ierr);
139929622bf0SStefano Zampini     ierr = VecAssemblyEnd(shell_ctx->work_small_1);CHKERRQ(ierr);
140029622bf0SStefano Zampini     ierr = MatSolve(small_mat,shell_ctx->work_small_1,shell_ctx->work_small_2);CHKERRQ(ierr);
140129622bf0SStefano Zampini     ierr = VecGetArray(shell_ctx->work_small_2,&array);CHKERRQ(ierr);
140229622bf0SStefano Zampini     for (i=0;i<basis_size;i++) {
140329622bf0SStefano Zampini       array_mat[i*basis_size+k]=array[i];
140429622bf0SStefano Zampini     }
140529622bf0SStefano Zampini     ierr = VecRestoreArray(shell_ctx->work_small_2,&array);CHKERRQ(ierr);
140629622bf0SStefano Zampini   }
140729622bf0SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_size,basis_size,array_mat,&inv_small_mat);CHKERRQ(ierr);
140829622bf0SStefano Zampini   ierr = MatMatMult(shell_ctx->basis_mat,inv_small_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&shell_ctx->Lbasis_mat);CHKERRQ(ierr);
140929622bf0SStefano Zampini   ierr = PetscFree(array_mat);CHKERRQ(ierr);
141029622bf0SStefano Zampini   ierr = MatDestroy(&inv_small_mat);CHKERRQ(ierr);
141129622bf0SStefano Zampini   ierr = MatDestroy(&small_mat);CHKERRQ(ierr);
141229622bf0SStefano Zampini   ierr = MatScale(shell_ctx->Kbasis_mat,m_one);CHKERRQ(ierr);
141329622bf0SStefano Zampini 
141429622bf0SStefano Zampini   /* Rebuild local PC */
141529622bf0SStefano Zampini   ierr = KSPGetPC(*local_ksp,&shell_ctx->local_pc);CHKERRQ(ierr);
141629622bf0SStefano Zampini   ierr = PetscObjectReference((PetscObject)shell_ctx->local_pc);CHKERRQ(ierr);
141729622bf0SStefano Zampini   ierr = PCCreate(PETSC_COMM_SELF,&newpc);CHKERRQ(ierr);
141829622bf0SStefano Zampini   ierr = PCSetOperators(newpc,local_mat,local_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
141929622bf0SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
142029622bf0SStefano Zampini   ierr = PCShellSetContext(newpc,shell_ctx);CHKERRQ(ierr);
142129622bf0SStefano Zampini   ierr = PCShellSetApply(newpc,PCBDDCApplyNullSpaceCorrectionPC);CHKERRQ(ierr);
142229622bf0SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyNullSpaceCorrectionPC);CHKERRQ(ierr);
142329622bf0SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
142429622bf0SStefano Zampini   ierr = KSPSetPC(*local_ksp,newpc);CHKERRQ(ierr);
142529622bf0SStefano Zampini   ierr = PCDestroy(&newpc);CHKERRQ(ierr);
142629622bf0SStefano Zampini   ierr = KSPSetUp(*local_ksp);CHKERRQ(ierr);
142729622bf0SStefano Zampini 
142829622bf0SStefano Zampini   /* test */
142929622bf0SStefano Zampini   if (pcbddc->dbg_flag) {
143029622bf0SStefano Zampini     PetscReal   test_err;
143129622bf0SStefano Zampini     KSP         check_ksp;
143229622bf0SStefano Zampini     PC          check_pc;
143329622bf0SStefano Zampini     PetscReal   lambda_min,lambda_max;
143429622bf0SStefano Zampini     Mat         test_mat;
143529622bf0SStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
143629622bf0SStefano Zampini     PetscBool   setsym,issym=PETSC_FALSE;
143729622bf0SStefano Zampini 
143829622bf0SStefano Zampini     ierr = KSPGetPC(*local_ksp,&check_pc);CHKERRQ(ierr);
143929622bf0SStefano Zampini     ierr = VecDuplicate(shell_ctx->work_full_1,&work1);CHKERRQ(ierr);
144029622bf0SStefano Zampini     ierr = VecDuplicate(shell_ctx->work_full_1,&work2);CHKERRQ(ierr);
144129622bf0SStefano Zampini     ierr = VecDuplicate(shell_ctx->work_full_1,&work3);CHKERRQ(ierr);
144229622bf0SStefano Zampini     ierr = VecSetRandom(shell_ctx->work_small_1,PETSC_NULL);CHKERRQ(ierr);
144329622bf0SStefano Zampini     ierr = MatMult(shell_ctx->basis_mat,shell_ctx->work_small_1,work1);CHKERRQ(ierr);
144429622bf0SStefano Zampini     ierr = VecCopy(work1,work2);CHKERRQ(ierr);
144529622bf0SStefano Zampini     ierr = MatMult(local_mat,work1,work3);CHKERRQ(ierr);
144629622bf0SStefano Zampini     ierr = PCApply(check_pc,work3,work1);CHKERRQ(ierr);
144729622bf0SStefano Zampini     ierr = VecAXPY(work1,m_one,work2);CHKERRQ(ierr);
144829622bf0SStefano Zampini     ierr = VecNorm(work1,NORM_INFINITY,&test_err);CHKERRQ(ierr);
144929622bf0SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d error for nullspace correction for ",PetscGlobalRank);
145029622bf0SStefano Zampini     if (basis_dofs == n_I) {
145129622bf0SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Dirichlet ");
145229622bf0SStefano Zampini     } else {
145329622bf0SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Neumann ");
145429622bf0SStefano Zampini     }
145529622bf0SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"solver is :%1.14e\n",test_err);
145629622bf0SStefano Zampini 
145729622bf0SStefano Zampini     ierr = MatTransposeMatMult(shell_ctx->Lbasis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&test_mat);CHKERRQ(ierr);
145829622bf0SStefano Zampini     ierr = MatShift(test_mat,one);CHKERRQ(ierr);
145929622bf0SStefano Zampini     ierr = MatNorm(test_mat,NORM_INFINITY,&test_err);CHKERRQ(ierr);
146029622bf0SStefano Zampini     ierr = MatDestroy(&test_mat);CHKERRQ(ierr);
146129622bf0SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d error for nullspace matrices is :%1.14e\n",PetscGlobalRank,test_err);
146229622bf0SStefano Zampini 
146329622bf0SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
146429622bf0SStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&check_ksp);CHKERRQ(ierr);
146529622bf0SStefano Zampini     ierr = KSPSetOperators(check_ksp,local_mat,local_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
146629622bf0SStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-8,1.e-8,PETSC_DEFAULT,basis_dofs);CHKERRQ(ierr);
146729622bf0SStefano Zampini     ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
146829622bf0SStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
146929622bf0SStefano Zampini     if (issym) {
147029622bf0SStefano Zampini       ierr = KSPSetType(check_ksp,KSPCG);CHKERRQ(ierr);
147129622bf0SStefano Zampini     }
147229622bf0SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
147329622bf0SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
147429622bf0SStefano Zampini     ierr = VecSetRandom(work1,PETSC_NULL);CHKERRQ(ierr);
147529622bf0SStefano Zampini     ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
147629622bf0SStefano Zampini     ierr = KSPSolve(check_ksp,work2,work2);CHKERRQ(ierr);
147729622bf0SStefano Zampini     ierr = VecAXPY(work2,m_one,work1);CHKERRQ(ierr);
147829622bf0SStefano Zampini     ierr = VecNorm(work2,NORM_INFINITY,&test_err);CHKERRQ(ierr);
147929622bf0SStefano Zampini     ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
148029622bf0SStefano Zampini     ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
148129622bf0SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d error for adapted KSP %1.14e (it %d, eigs %1.6e %1.6e)\n",PetscGlobalRank,test_err,k,lambda_min,lambda_max);
148229622bf0SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
148329622bf0SStefano Zampini     ierr = VecDestroy(&work1);CHKERRQ(ierr);
148429622bf0SStefano Zampini     ierr = VecDestroy(&work2);CHKERRQ(ierr);
148529622bf0SStefano Zampini     ierr = VecDestroy(&work3);CHKERRQ(ierr);
148629622bf0SStefano Zampini   }
148729622bf0SStefano Zampini   PetscFunctionReturn(0);
148829622bf0SStefano Zampini }
148929622bf0SStefano Zampini 
149029622bf0SStefano Zampini #undef __FUNCT__
14912e8d2280SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
14922e8d2280SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool use)
14932e8d2280SStefano Zampini {
14942e8d2280SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
14952e8d2280SStefano Zampini 
14962e8d2280SStefano Zampini   PetscFunctionBegin;
14972e8d2280SStefano Zampini   pcbddc->use_exact_dirichlet=use;
14982e8d2280SStefano Zampini   PetscFunctionReturn(0);
14992e8d2280SStefano Zampini }
15002e8d2280SStefano Zampini 
15012e8d2280SStefano Zampini #undef __FUNCT__
15024fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
15034fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
15044fad6a16SStefano Zampini {
15054fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15064fad6a16SStefano Zampini 
15074fad6a16SStefano Zampini   PetscFunctionBegin;
15084fad6a16SStefano Zampini   pcbddc->current_level=level;
15094fad6a16SStefano Zampini   PetscFunctionReturn(0);
15104fad6a16SStefano Zampini }
15113425bc38SStefano Zampini 
15123425bc38SStefano Zampini #undef __FUNCT__
15130bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCAdaptNullSpace"
15140bdf917eSStefano Zampini static PetscErrorCode PCBDDCAdaptNullSpace(PC pc)
15150bdf917eSStefano Zampini {
15160bdf917eSStefano Zampini   PC_IS*         pcis = (PC_IS*)  (pc->data);
15170bdf917eSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
15180bdf917eSStefano Zampini   KSP            inv_change;
15190bdf917eSStefano Zampini   PC             pc_change;
15200bdf917eSStefano Zampini   const Vec      *nsp_vecs;
15210bdf917eSStefano Zampini   Vec            *new_nsp_vecs;
15220bdf917eSStefano Zampini   PetscInt       i,nsp_size,new_nsp_size,start_new;
15230bdf917eSStefano Zampini   PetscBool      nsp_has_cnst;
15240bdf917eSStefano Zampini   MatNullSpace   new_nsp;
15250bdf917eSStefano Zampini   PetscErrorCode ierr;
15260bdf917eSStefano Zampini 
15270bdf917eSStefano Zampini   PetscFunctionBegin;
15280bdf917eSStefano Zampini   ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr);
15290bdf917eSStefano Zampini   ierr = KSPCreate(PETSC_COMM_SELF,&inv_change);CHKERRQ(ierr);
15300bdf917eSStefano Zampini   ierr = KSPSetOperators(inv_change,pcbddc->ChangeOfBasisMatrix,pcbddc->ChangeOfBasisMatrix,SAME_PRECONDITIONER);CHKERRQ(ierr);
15310bdf917eSStefano Zampini   ierr = KSPSetType(inv_change,KSPPREONLY);CHKERRQ(ierr);
15320bdf917eSStefano Zampini   ierr = KSPGetPC(inv_change,&pc_change);CHKERRQ(ierr);
15330bdf917eSStefano Zampini   ierr = PCSetType(pc_change,PCLU);CHKERRQ(ierr);
15340bdf917eSStefano Zampini   ierr = KSPSetUp(inv_change);CHKERRQ(ierr);
15350bdf917eSStefano Zampini   new_nsp_size = nsp_size;
15360bdf917eSStefano Zampini   if (nsp_has_cnst) { new_nsp_size++; }
15370bdf917eSStefano Zampini   ierr = PetscMalloc(new_nsp_size*sizeof(Vec),&new_nsp_vecs);CHKERRQ(ierr);
15380bdf917eSStefano Zampini   for (i=0;i<new_nsp_size;i++) { ierr = VecDuplicate(pcis->vec1_global,&new_nsp_vecs[i]);CHKERRQ(ierr); }
15390bdf917eSStefano Zampini   start_new = 0;
15400bdf917eSStefano Zampini   if (nsp_has_cnst) {
15410bdf917eSStefano Zampini     start_new = 1;
15420bdf917eSStefano Zampini     ierr = VecSet(new_nsp_vecs[0],1.0);CHKERRQ(ierr);
15430bdf917eSStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
15440bdf917eSStefano Zampini     ierr = KSPSolve(inv_change,pcis->vec1_B,pcis->vec1_B);
15450bdf917eSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[0],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15460bdf917eSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[0],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15470bdf917eSStefano Zampini   }
15480bdf917eSStefano Zampini   for (i=0;i<nsp_size;i++) {
15490bdf917eSStefano Zampini     ierr = VecCopy(nsp_vecs[i],new_nsp_vecs[i+start_new]);CHKERRQ(ierr);
15500bdf917eSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,nsp_vecs[i],pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15510bdf917eSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,nsp_vecs[i],pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15520bdf917eSStefano Zampini     ierr = KSPSolve(inv_change,pcis->vec1_B,pcis->vec1_B);
15530bdf917eSStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[i+start_new],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15540bdf917eSStefano Zampini     ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[i+start_new],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15550bdf917eSStefano Zampini   }
15560bdf917eSStefano Zampini   ierr = VecNormalize(new_nsp_vecs[0],PETSC_NULL);CHKERRQ(ierr);
15570bdf917eSStefano Zampini   /* TODO : Orthonormalize vecs when new_nsp_size > 0! */
15580bdf917eSStefano Zampini 
15590bdf917eSStefano Zampini   ierr = KSPDestroy(&inv_change);CHKERRQ(ierr);
15600bdf917eSStefano Zampini   ierr = MatNullSpaceCreate(((PetscObject)pc)->comm,PETSC_FALSE,new_nsp_size,new_nsp_vecs,&new_nsp);CHKERRQ(ierr);
15610bdf917eSStefano Zampini   ierr = PCBDDCSetNullSpace(pc,new_nsp);CHKERRQ(ierr);
15620bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&new_nsp);CHKERRQ(ierr);
15630bdf917eSStefano Zampini   /*
15640bdf917eSStefano Zampini   ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr);
15650bdf917eSStefano Zampini   printf("New Null Space, mat changed: %d\n",nsp_t);
15660bdf917eSStefano Zampini     temp_mat = matis->A;
15670bdf917eSStefano Zampini     matis->A = pcbddc->local_mat;
15680bdf917eSStefano Zampini     pcbddc->local_mat = temp_mat;
15690bdf917eSStefano Zampini   ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr);
15700bdf917eSStefano Zampini   printf("New Null Space, mat original: %d\n",nsp_t);*/
15710bdf917eSStefano Zampini 
15720bdf917eSStefano Zampini   for (i=0;i<new_nsp_size;i++) { ierr = VecDestroy(&new_nsp_vecs[i]);CHKERRQ(ierr); }
15730bdf917eSStefano Zampini   ierr = PetscFree(new_nsp_vecs);CHKERRQ(ierr);
15740bdf917eSStefano Zampini   PetscFunctionReturn(0);
15750bdf917eSStefano Zampini }
15760bdf917eSStefano Zampini 
15770bdf917eSStefano Zampini #undef __FUNCT__
15783425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPMatContext"
15793425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPMatContext(PC pc, FETIDPMat_ctx **fetidpmat_ctx)
15803425bc38SStefano Zampini {
15813425bc38SStefano Zampini   FETIDPMat_ctx  *newctx;
15823425bc38SStefano Zampini   PetscErrorCode ierr;
15833425bc38SStefano Zampini 
15843425bc38SStefano Zampini   PetscFunctionBegin;
15853425bc38SStefano Zampini   ierr = PetscMalloc(sizeof(*newctx),&newctx);CHKERRQ(ierr);
15863425bc38SStefano Zampini   newctx->lambda_local    = 0;
15873425bc38SStefano Zampini   newctx->temp_solution_B = 0;
15883425bc38SStefano Zampini   newctx->temp_solution_D = 0;
15893425bc38SStefano Zampini   newctx->B_delta         = 0;
15903425bc38SStefano Zampini   newctx->B_Ddelta        = 0; /* theoretically belongs to the FETIDP preconditioner */
15913425bc38SStefano Zampini   newctx->l2g_lambda      = 0;
15923425bc38SStefano Zampini   /* increase the reference count for BDDC preconditioner */
15933425bc38SStefano Zampini   ierr = PetscObjectReference((PetscObject)pc);CHKERRQ(ierr);
15943425bc38SStefano Zampini   newctx->pc              = pc;
15953425bc38SStefano Zampini   *fetidpmat_ctx          = newctx;
15963425bc38SStefano Zampini   PetscFunctionReturn(0);
15973425bc38SStefano Zampini }
15983425bc38SStefano Zampini 
15993425bc38SStefano Zampini #undef __FUNCT__
16003425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPPCContext"
16013425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPPCContext(PC pc, FETIDPPC_ctx **fetidppc_ctx)
16023425bc38SStefano Zampini {
16033425bc38SStefano Zampini   FETIDPPC_ctx  *newctx;
16043425bc38SStefano Zampini   PetscErrorCode ierr;
16053425bc38SStefano Zampini 
16063425bc38SStefano Zampini   PetscFunctionBegin;
16073425bc38SStefano Zampini   ierr = PetscMalloc(sizeof(*newctx),&newctx);CHKERRQ(ierr);
16083425bc38SStefano Zampini   newctx->lambda_local    = 0;
16093425bc38SStefano Zampini   newctx->B_Ddelta        = 0;
16103425bc38SStefano Zampini   newctx->l2g_lambda      = 0;
16113425bc38SStefano Zampini   /* increase the reference count for BDDC preconditioner */
16123425bc38SStefano Zampini   ierr = PetscObjectReference((PetscObject)pc);CHKERRQ(ierr);
16133425bc38SStefano Zampini   newctx->pc              = pc;
16143425bc38SStefano Zampini   *fetidppc_ctx           = newctx;
16153425bc38SStefano Zampini   PetscFunctionReturn(0);
16163425bc38SStefano Zampini }
16173425bc38SStefano Zampini 
16183425bc38SStefano Zampini #undef __FUNCT__
16193425bc38SStefano Zampini #define __FUNCT__ "PCBDDCDestroyFETIDPMat"
16203425bc38SStefano Zampini static PetscErrorCode PCBDDCDestroyFETIDPMat(Mat A)
16213425bc38SStefano Zampini {
16223425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
16233425bc38SStefano Zampini   PetscErrorCode ierr;
16243425bc38SStefano Zampini 
16253425bc38SStefano Zampini   PetscFunctionBegin;
16263425bc38SStefano Zampini   ierr = MatShellGetContext(A,(void**)&mat_ctx);CHKERRQ(ierr);
16273425bc38SStefano Zampini   ierr = VecDestroy(&mat_ctx->lambda_local);CHKERRQ(ierr);
16283425bc38SStefano Zampini   ierr = VecDestroy(&mat_ctx->temp_solution_D);CHKERRQ(ierr);
16293425bc38SStefano Zampini   ierr = VecDestroy(&mat_ctx->temp_solution_B);CHKERRQ(ierr);
16303425bc38SStefano Zampini   ierr = MatDestroy(&mat_ctx->B_delta);CHKERRQ(ierr);
16313425bc38SStefano Zampini   ierr = MatDestroy(&mat_ctx->B_Ddelta);CHKERRQ(ierr);
16323425bc38SStefano Zampini   ierr = VecScatterDestroy(&mat_ctx->l2g_lambda);CHKERRQ(ierr);
16333425bc38SStefano Zampini   ierr = PCDestroy(&mat_ctx->pc);CHKERRQ(ierr); /* actually it does not destroy BDDC, only decrease its reference count */
16343425bc38SStefano Zampini   ierr = PetscFree(mat_ctx);CHKERRQ(ierr);
16353425bc38SStefano Zampini   PetscFunctionReturn(0);
16363425bc38SStefano Zampini }
16373425bc38SStefano Zampini 
16383425bc38SStefano Zampini #undef __FUNCT__
16393425bc38SStefano Zampini #define __FUNCT__ "PCBDDCDestroyFETIDPPC"
16403425bc38SStefano Zampini static PetscErrorCode PCBDDCDestroyFETIDPPC(PC pc)
16413425bc38SStefano Zampini {
16423425bc38SStefano Zampini   FETIDPPC_ctx  *pc_ctx;
16433425bc38SStefano Zampini   PetscErrorCode ierr;
16443425bc38SStefano Zampini 
16453425bc38SStefano Zampini   PetscFunctionBegin;
16463425bc38SStefano Zampini   ierr = PCShellGetContext(pc,(void**)&pc_ctx);CHKERRQ(ierr);
16473425bc38SStefano Zampini   ierr = VecDestroy(&pc_ctx->lambda_local);CHKERRQ(ierr);
16483425bc38SStefano Zampini   ierr = MatDestroy(&pc_ctx->B_Ddelta);CHKERRQ(ierr);
16493425bc38SStefano Zampini   ierr = VecScatterDestroy(&pc_ctx->l2g_lambda);CHKERRQ(ierr);
16503425bc38SStefano Zampini   ierr = PCDestroy(&pc_ctx->pc);CHKERRQ(ierr); /* actually it does not destroy BDDC, only decrease its reference count */
16513425bc38SStefano Zampini   ierr = PetscFree(pc_ctx);CHKERRQ(ierr);
16523425bc38SStefano Zampini   PetscFunctionReturn(0);
16533425bc38SStefano Zampini }
16543425bc38SStefano Zampini 
16553425bc38SStefano Zampini #undef __FUNCT__
16563425bc38SStefano Zampini #define __FUNCT__ "PCBDDCSetupFETIDPMatContext"
16573425bc38SStefano Zampini static PetscErrorCode PCBDDCSetupFETIDPMatContext(FETIDPMat_ctx *fetidpmat_ctx)
16583425bc38SStefano Zampini {
16593425bc38SStefano Zampini   PetscErrorCode ierr;
16603425bc38SStefano Zampini   PC_IS          *pcis=(PC_IS*)fetidpmat_ctx->pc->data;
16613425bc38SStefano Zampini   PC_BDDC        *pcbddc=(PC_BDDC*)fetidpmat_ctx->pc->data;
16623425bc38SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
16633425bc38SStefano Zampini   Mat_IS         *matis  = (Mat_IS*)fetidpmat_ctx->pc->pmat->data;
16643425bc38SStefano Zampini   MPI_Comm       comm = ((PetscObject)(fetidpmat_ctx->pc))->comm;
16653425bc38SStefano Zampini 
16663425bc38SStefano Zampini   Mat            ScalingMat;
16673425bc38SStefano Zampini   Vec            lambda_global;
16683425bc38SStefano Zampini   IS             IS_l2g_lambda;
16693425bc38SStefano Zampini 
16703425bc38SStefano Zampini   PetscBool      skip_node,fully_redundant;
1671ef028eecSStefano Zampini   PetscInt       i,j,k,s,n_boundary_dofs,n_global_lambda,n_vertices,partial_sum;
16723425bc38SStefano Zampini   PetscInt       n_local_lambda,n_lambda_for_dof,dual_size,n_neg_values,n_pos_values;
1673ef028eecSStefano Zampini   PetscMPIInt    rank,nprocs;
16743425bc38SStefano Zampini   PetscScalar    scalar_value;
16753425bc38SStefano Zampini 
16763425bc38SStefano Zampini   PetscInt       *vertex_indices,*temp_indices;
16773425bc38SStefano Zampini   PetscInt       *dual_dofs_boundary_indices,*aux_local_numbering_1,*aux_global_numbering;
16783425bc38SStefano Zampini   PetscInt       *aux_sums,*cols_B_delta,*l2g_indices;
16793425bc38SStefano Zampini   PetscScalar    *array,*scaling_factors,*vals_B_delta;
1680ef028eecSStefano Zampini   PetscInt       *aux_local_numbering_2,*dof_sizes,*dof_displs;
1681ef028eecSStefano Zampini   PetscInt       first_index,old_index;
1682ef028eecSStefano Zampini   PetscBool      first_found = PETSC_FALSE;
16833425bc38SStefano Zampini 
16843425bc38SStefano Zampini   /* For communication of scaling factors */
16853425bc38SStefano Zampini   PetscInt       *ptrs_buffer,neigh_position;
16863425bc38SStefano Zampini   PetscScalar    **all_factors,*send_buffer,*recv_buffer;
16873425bc38SStefano Zampini   MPI_Request    *send_reqs,*recv_reqs;
16883425bc38SStefano Zampini 
16893425bc38SStefano Zampini   /* tests */
16903425bc38SStefano Zampini   Vec            test_vec;
16913425bc38SStefano Zampini   PetscBool      test_fetidp;
16923425bc38SStefano Zampini   PetscViewer    viewer;
16933425bc38SStefano Zampini 
16943425bc38SStefano Zampini   PetscFunctionBegin;
16953425bc38SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
16963425bc38SStefano Zampini   ierr = MPI_Comm_size(comm,&nprocs);CHKERRQ(ierr);
16973425bc38SStefano Zampini 
16983425bc38SStefano Zampini   /* Default type of lagrange multipliers is non-redundant */
16993425bc38SStefano Zampini   fully_redundant = PETSC_FALSE;
17003425bc38SStefano Zampini   ierr = PetscOptionsGetBool(PETSC_NULL,"-fetidp_fullyredundant",&fully_redundant,PETSC_NULL);CHKERRQ(ierr);
17013425bc38SStefano Zampini 
17023425bc38SStefano Zampini   /* Evaluate local and global number of lagrange multipliers */
17033425bc38SStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
17043425bc38SStefano Zampini   n_local_lambda = 0;
17053425bc38SStefano Zampini   partial_sum = 0;
17063425bc38SStefano Zampini   n_boundary_dofs = 0;
17073425bc38SStefano Zampini   s = 0;
17083425bc38SStefano Zampini   n_vertices = 0;
17093425bc38SStefano Zampini   /* Get Vertices used to define the BDDC */
17103425bc38SStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(*vertex_indices),&vertex_indices);CHKERRQ(ierr);
17113425bc38SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
17123425bc38SStefano Zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&j,(const PetscInt**)&temp_indices,PETSC_NULL);CHKERRQ(ierr);
17133425bc38SStefano Zampini     if (j == 1) {
17143425bc38SStefano Zampini       vertex_indices[n_vertices]=temp_indices[0];
17153425bc38SStefano Zampini       n_vertices++;
17163425bc38SStefano Zampini     }
17173425bc38SStefano Zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&j,(const PetscInt**)&temp_indices,PETSC_NULL);CHKERRQ(ierr);
17183425bc38SStefano Zampini   }
17193425bc38SStefano Zampini   dual_size = pcis->n_B-n_vertices;
1720f0474715SStefano Zampini   ierr = PetscSortInt(n_vertices,vertex_indices);CHKERRQ(ierr);
17213425bc38SStefano Zampini   ierr = PetscMalloc(dual_size*sizeof(*dual_dofs_boundary_indices),&dual_dofs_boundary_indices);CHKERRQ(ierr);
17223425bc38SStefano Zampini   ierr = PetscMalloc(dual_size*sizeof(*aux_local_numbering_1),&aux_local_numbering_1);CHKERRQ(ierr);
17233425bc38SStefano Zampini   ierr = PetscMalloc(dual_size*sizeof(*aux_local_numbering_2),&aux_local_numbering_2);CHKERRQ(ierr);
17243425bc38SStefano Zampini 
17253425bc38SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
17263425bc38SStefano Zampini   for (i=0;i<pcis->n;i++) {
17273425bc38SStefano Zampini     j = mat_graph->count[i]; /* RECALL: mat_graph->count[i] does not count myself */
1728c6582918SStefano Zampini     k = 0;
1729c6582918SStefano Zampini     if (j > 0) {
17303425bc38SStefano Zampini       k = (mat_graph->neighbours_set[i][0] == -1 ?  1 : 0);
1731c6582918SStefano Zampini     }
17323425bc38SStefano Zampini     j = j - k ;
17333425bc38SStefano Zampini     if (j > 0) { n_boundary_dofs++; }
17343425bc38SStefano Zampini 
17353425bc38SStefano Zampini     skip_node = PETSC_FALSE;
1736c6582918SStefano Zampini     if (s < n_vertices && vertex_indices[s]==i) { /* it works for a sorted set of vertices */
17373425bc38SStefano Zampini       skip_node = PETSC_TRUE;
17383425bc38SStefano Zampini       s++;
17393425bc38SStefano Zampini     }
17403425bc38SStefano Zampini     if (j < 1) {skip_node = PETSC_TRUE;}
17413425bc38SStefano Zampini     if (!skip_node) {
17423425bc38SStefano Zampini       if (fully_redundant) {
17433425bc38SStefano Zampini         /* fully redundant set of lagrange multipliers */
17443425bc38SStefano Zampini         n_lambda_for_dof = (j*(j+1))/2;
17453425bc38SStefano Zampini       } else {
17463425bc38SStefano Zampini         n_lambda_for_dof = j;
17473425bc38SStefano Zampini       }
17483425bc38SStefano Zampini       n_local_lambda += j;
17493425bc38SStefano Zampini       /* needed to evaluate global number of lagrange multipliers */
17503425bc38SStefano Zampini       array[i]=(1.0*n_lambda_for_dof)/(j+1.0); /* already scaled for the next global sum */
17513425bc38SStefano Zampini       /* store some data needed */
17523425bc38SStefano Zampini       dual_dofs_boundary_indices[partial_sum] = n_boundary_dofs-1;
17533425bc38SStefano Zampini       aux_local_numbering_1[partial_sum] = i;
1754ef028eecSStefano Zampini       aux_local_numbering_2[partial_sum] = n_lambda_for_dof;
17553425bc38SStefano Zampini       partial_sum++;
17563425bc38SStefano Zampini     }
17573425bc38SStefano Zampini   }
17583425bc38SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1759ef028eecSStefano Zampini 
17603425bc38SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
17613425bc38SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17623425bc38SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17633425bc38SStefano Zampini   ierr = VecSum(pcis->vec1_global,&scalar_value);CHKERRQ(ierr);
17643425bc38SStefano Zampini   fetidpmat_ctx->n_lambda = (PetscInt) scalar_value;
17653425bc38SStefano Zampini   /* printf("I found %d global multipliers (%f)\n",fetidpmat_ctx->n_lambda,scalar_value); */
17663425bc38SStefano Zampini 
17673425bc38SStefano Zampini   /* compute global ordering of lagrange multipliers and associate l2g map */
1768ef028eecSStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
1769ef028eecSStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
1770ef028eecSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1771ef028eecSStefano Zampini   for (i=0;i<dual_size;i++) {
1772ef028eecSStefano Zampini     array[aux_local_numbering_1[i]] = aux_local_numbering_2[i];
1773ef028eecSStefano Zampini   }
1774ef028eecSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1775ef028eecSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1776ef028eecSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1777ef028eecSStefano Zampini   ierr = VecSum(pcis->vec1_global,&scalar_value);CHKERRQ(ierr);
1778ef028eecSStefano Zampini   if (pcbddc->dbg_flag && (PetscInt)scalar_value != fetidpmat_ctx->n_lambda) {
1779acee19a7SJed Brown     SETERRQ2(PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Global number of multipliers mismatch! (%d!=%d)\n",(PetscInt)scalar_value,fetidpmat_ctx->n_lambda);
1780ef028eecSStefano Zampini   }
17813425bc38SStefano Zampini 
1782ef028eecSStefano Zampini   /* Fill pcis->vec1_global with cumulative function for global numbering */
1783ef028eecSStefano Zampini   ierr = VecGetArray(pcis->vec1_global,&array);CHKERRQ(ierr);
1784ef028eecSStefano Zampini   ierr = VecGetLocalSize(pcis->vec1_global,&s);CHKERRQ(ierr);
1785ef028eecSStefano Zampini   k = 0;
1786ef028eecSStefano Zampini   first_index = -1;
1787ef028eecSStefano Zampini   for (i=0;i<s;i++) {
1788ef028eecSStefano Zampini     if (!first_found && array[i] > 0.0) {
1789ef028eecSStefano Zampini       first_found = PETSC_TRUE;
1790ef028eecSStefano Zampini       first_index = i;
1791ef028eecSStefano Zampini     }
1792ef028eecSStefano Zampini     k += (PetscInt)array[i];
1793ef028eecSStefano Zampini   }
1794ef028eecSStefano Zampini   j = (!rank ? nprocs : 0);
17953425bc38SStefano Zampini   ierr = PetscMalloc(j*sizeof(*dof_sizes),&dof_sizes);CHKERRQ(ierr);
17963425bc38SStefano Zampini   ierr = PetscMalloc(j*sizeof(*dof_displs),&dof_displs);CHKERRQ(ierr);
1797ef028eecSStefano Zampini   ierr = MPI_Gather(&k,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
1798ef028eecSStefano Zampini   if (!rank) {
17993425bc38SStefano Zampini     dof_displs[0]=0;
18003425bc38SStefano Zampini     for (i=1;i<nprocs;i++) {
18013425bc38SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
18023425bc38SStefano Zampini     }
18033425bc38SStefano Zampini   }
1804ef028eecSStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&k,1,MPIU_INT,0,comm);CHKERRQ(ierr);
1805ef028eecSStefano Zampini   if (first_found) {
1806ef028eecSStefano Zampini     array[first_index] += k;
1807ef028eecSStefano Zampini     old_index = first_index;
1808ef028eecSStefano Zampini     for (i=first_index+1;i<s;i++) {
1809ef028eecSStefano Zampini       if (array[i] > 0.0) {
1810ef028eecSStefano Zampini         array[i] += array[old_index];
1811ef028eecSStefano Zampini         old_index = i;
1812ef028eecSStefano Zampini       }
1813ef028eecSStefano Zampini     }
1814ef028eecSStefano Zampini   }
1815ef028eecSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_global,&array);CHKERRQ(ierr);
1816ef028eecSStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
1817ef028eecSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1818ef028eecSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1819ef028eecSStefano Zampini   ierr = PetscMalloc(dual_size*sizeof(*aux_global_numbering),&aux_global_numbering);CHKERRQ(ierr);
1820ef028eecSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18213425bc38SStefano Zampini   for (i=0;i<dual_size;i++) {
1822ef028eecSStefano Zampini     aux_global_numbering[i] = (PetscInt)array[aux_local_numbering_1[i]]-aux_local_numbering_2[i];
18233425bc38SStefano Zampini   }
1824ef028eecSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1825f0474715SStefano Zampini   ierr = PetscFree(aux_local_numbering_2);CHKERRQ(ierr);
1826f0474715SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
1827f0474715SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
18283425bc38SStefano Zampini 
18293425bc38SStefano Zampini   /* init data for scaling factors exchange */
18303425bc38SStefano Zampini   partial_sum = 0;
18313425bc38SStefano Zampini   j = 0;
18323425bc38SStefano Zampini   ierr = PetscMalloc(pcis->n_neigh*sizeof(PetscInt),&ptrs_buffer);CHKERRQ(ierr);
18333425bc38SStefano Zampini   ierr = PetscMalloc((pcis->n_neigh-1)*sizeof(MPI_Request),&send_reqs);CHKERRQ(ierr);
18343425bc38SStefano Zampini   ierr = PetscMalloc((pcis->n_neigh-1)*sizeof(MPI_Request),&recv_reqs);CHKERRQ(ierr);
18353425bc38SStefano Zampini   ierr = PetscMalloc(pcis->n*sizeof(PetscScalar*),&all_factors);CHKERRQ(ierr);
18363425bc38SStefano Zampini   ptrs_buffer[0]=0;
18373425bc38SStefano Zampini   for (i=1;i<pcis->n_neigh;i++) {
18383425bc38SStefano Zampini     partial_sum += pcis->n_shared[i];
18393425bc38SStefano Zampini     ptrs_buffer[i] = ptrs_buffer[i-1]+pcis->n_shared[i];
18403425bc38SStefano Zampini   }
18413425bc38SStefano Zampini   ierr = PetscMalloc(partial_sum*sizeof(PetscScalar),&send_buffer);CHKERRQ(ierr);
18423425bc38SStefano Zampini   ierr = PetscMalloc(partial_sum*sizeof(PetscScalar),&recv_buffer);CHKERRQ(ierr);
18433425bc38SStefano Zampini   ierr = PetscMalloc(partial_sum*sizeof(PetscScalar),&all_factors[0]);CHKERRQ(ierr);
18443425bc38SStefano Zampini   for (i=0;i<pcis->n-1;i++) {
18453425bc38SStefano Zampini     j = mat_graph->count[i];
18463425bc38SStefano Zampini     if (j>0) {
18473425bc38SStefano Zampini       k = (mat_graph->neighbours_set[i][0] == -1 ?  1 : 0);
18483425bc38SStefano Zampini       j = j - k;
18493425bc38SStefano Zampini     }
18503425bc38SStefano Zampini     all_factors[i+1]=all_factors[i]+j;
18513425bc38SStefano Zampini   }
18523425bc38SStefano Zampini   /* scatter B scaling to N vec */
18533425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->N_to_B,pcis->D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18543425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->N_to_B,pcis->D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18553425bc38SStefano Zampini   /* communications */
18563425bc38SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18573425bc38SStefano Zampini   for (i=1;i<pcis->n_neigh;i++) {
18583425bc38SStefano Zampini     for (j=0;j<pcis->n_shared[i];j++) {
18593425bc38SStefano Zampini       send_buffer[ptrs_buffer[i-1]+j]=array[pcis->shared[i][j]];
18603425bc38SStefano Zampini     }
18613425bc38SStefano Zampini     j = ptrs_buffer[i]-ptrs_buffer[i-1];
1862ea7e1babSStefano Zampini     ierr = MPI_Isend(&send_buffer[ptrs_buffer[i-1]],j,MPIU_SCALAR,pcis->neigh[i],0,comm,&send_reqs[i-1]);CHKERRQ(ierr);
1863ea7e1babSStefano Zampini     ierr = MPI_Irecv(&recv_buffer[ptrs_buffer[i-1]],j,MPIU_SCALAR,pcis->neigh[i],0,comm,&recv_reqs[i-1]);CHKERRQ(ierr);
18643425bc38SStefano Zampini   }
18653425bc38SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1866ea7e1babSStefano Zampini   ierr = MPI_Waitall((pcis->n_neigh-1),recv_reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
18673425bc38SStefano Zampini   /* put values in correct places */
18683425bc38SStefano Zampini   for (i=1;i<pcis->n_neigh;i++) {
18693425bc38SStefano Zampini     for (j=0;j<pcis->n_shared[i];j++) {
18703425bc38SStefano Zampini       k = pcis->shared[i][j];
18713425bc38SStefano Zampini       neigh_position = 0;
18723425bc38SStefano Zampini       while (mat_graph->neighbours_set[k][neigh_position] != pcis->neigh[i]) {neigh_position++;}
18733425bc38SStefano Zampini       s = (mat_graph->neighbours_set[k][0] == -1 ?  1 : 0);
18743425bc38SStefano Zampini       neigh_position = neigh_position - s;
18753425bc38SStefano Zampini       all_factors[k][neigh_position]=recv_buffer[ptrs_buffer[i-1]+j];
18763425bc38SStefano Zampini     }
18773425bc38SStefano Zampini   }
1878ea7e1babSStefano Zampini   ierr = MPI_Waitall((pcis->n_neigh-1),send_reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
18793425bc38SStefano Zampini   ierr = PetscFree(send_reqs);CHKERRQ(ierr);
18803425bc38SStefano Zampini   ierr = PetscFree(recv_reqs);CHKERRQ(ierr);
18813425bc38SStefano Zampini   ierr = PetscFree(send_buffer);CHKERRQ(ierr);
18823425bc38SStefano Zampini   ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
18833425bc38SStefano Zampini   ierr = PetscFree(ptrs_buffer);CHKERRQ(ierr);
18843425bc38SStefano Zampini 
18853425bc38SStefano Zampini   /* Compute B and B_delta (local actions) */
18863425bc38SStefano Zampini   ierr = PetscMalloc(pcis->n_neigh*sizeof(*aux_sums),&aux_sums);CHKERRQ(ierr);
18873425bc38SStefano Zampini   ierr = PetscMalloc(n_local_lambda*sizeof(*l2g_indices),&l2g_indices);CHKERRQ(ierr);
18883425bc38SStefano Zampini   ierr = PetscMalloc(n_local_lambda*sizeof(*vals_B_delta),&vals_B_delta);CHKERRQ(ierr);
18893425bc38SStefano Zampini   ierr = PetscMalloc(n_local_lambda*sizeof(*cols_B_delta),&cols_B_delta);CHKERRQ(ierr);
18903425bc38SStefano Zampini   ierr = PetscMalloc(n_local_lambda*sizeof(*scaling_factors),&scaling_factors);CHKERRQ(ierr);
18913425bc38SStefano Zampini   n_global_lambda=0;
18923425bc38SStefano Zampini   partial_sum=0;
18933425bc38SStefano Zampini   for (i=0;i<dual_size;i++) {
1894ef028eecSStefano Zampini     n_global_lambda = aux_global_numbering[i];
18953425bc38SStefano Zampini     j = mat_graph->count[aux_local_numbering_1[i]];
18963425bc38SStefano Zampini     k = (mat_graph->neighbours_set[aux_local_numbering_1[i]][0] == -1 ?  1 : 0);
18973425bc38SStefano Zampini     j = j - k;
18983425bc38SStefano Zampini     aux_sums[0]=0;
18993425bc38SStefano Zampini     for (s=1;s<j;s++) {
19003425bc38SStefano Zampini       aux_sums[s]=aux_sums[s-1]+j-s+1;
19013425bc38SStefano Zampini     }
19023425bc38SStefano Zampini     array = all_factors[aux_local_numbering_1[i]];
19033425bc38SStefano Zampini     n_neg_values = 0;
19043425bc38SStefano Zampini     while (n_neg_values < j && mat_graph->neighbours_set[aux_local_numbering_1[i]][n_neg_values+k] < rank) {n_neg_values++;}
19053425bc38SStefano Zampini     n_pos_values = j - n_neg_values;
19063425bc38SStefano Zampini     if (fully_redundant) {
19073425bc38SStefano Zampini       for (s=0;s<n_neg_values;s++) {
19083425bc38SStefano Zampini         l2g_indices    [partial_sum+s]=aux_sums[s]+n_neg_values-s-1+n_global_lambda;
19093425bc38SStefano Zampini         cols_B_delta   [partial_sum+s]=dual_dofs_boundary_indices[i];
19103425bc38SStefano Zampini         vals_B_delta   [partial_sum+s]=-1.0;
19113425bc38SStefano Zampini         scaling_factors[partial_sum+s]=array[s];
19123425bc38SStefano Zampini       }
19133425bc38SStefano Zampini       for (s=0;s<n_pos_values;s++) {
19143425bc38SStefano Zampini         l2g_indices    [partial_sum+s+n_neg_values]=aux_sums[n_neg_values]+s+n_global_lambda;
19153425bc38SStefano Zampini         cols_B_delta   [partial_sum+s+n_neg_values]=dual_dofs_boundary_indices[i];
19163425bc38SStefano Zampini         vals_B_delta   [partial_sum+s+n_neg_values]=1.0;
19173425bc38SStefano Zampini         scaling_factors[partial_sum+s+n_neg_values]=array[s+n_neg_values];
19183425bc38SStefano Zampini       }
19193425bc38SStefano Zampini       partial_sum += j;
19203425bc38SStefano Zampini     } else {
19213425bc38SStefano Zampini       /* l2g_indices and default cols and vals of B_delta */
19223425bc38SStefano Zampini       for (s=0;s<j;s++) {
19233425bc38SStefano Zampini         l2g_indices    [partial_sum+s]=n_global_lambda+s;
19243425bc38SStefano Zampini         cols_B_delta   [partial_sum+s]=dual_dofs_boundary_indices[i];
19253425bc38SStefano Zampini         vals_B_delta   [partial_sum+s]=0.0;
19263425bc38SStefano Zampini       }
19273425bc38SStefano Zampini       /* B_delta */
19283425bc38SStefano Zampini       if (n_neg_values > 0) { /* there's a rank next to me to the left */
19293425bc38SStefano Zampini         vals_B_delta   [partial_sum+n_neg_values-1]=-1.0;
19303425bc38SStefano Zampini       }
19313425bc38SStefano Zampini       if (n_neg_values < j) { /* there's a rank next to me to the right */
19323425bc38SStefano Zampini         vals_B_delta   [partial_sum+n_neg_values]=1.0;
19333425bc38SStefano Zampini       }
19343425bc38SStefano Zampini       /* scaling as in Klawonn-Widlund 1999*/
19353425bc38SStefano Zampini       for (s=0;s<n_neg_values;s++) {
19363425bc38SStefano Zampini         scalar_value = 0.0;
19373425bc38SStefano Zampini         for (k=0;k<s+1;k++) {
19383425bc38SStefano Zampini           scalar_value += array[k];
19393425bc38SStefano Zampini         }
1940ef028eecSStefano Zampini         scaling_factors[partial_sum+s] = -scalar_value;
19413425bc38SStefano Zampini       }
19423425bc38SStefano Zampini       for (s=0;s<n_pos_values;s++) {
19433425bc38SStefano Zampini         scalar_value = 0.0;
19443425bc38SStefano Zampini         for (k=s+n_neg_values;k<j;k++) {
19453425bc38SStefano Zampini           scalar_value += array[k];
19463425bc38SStefano Zampini         }
19473425bc38SStefano Zampini         scaling_factors[partial_sum+s+n_neg_values] = scalar_value;
19483425bc38SStefano Zampini       }
19493425bc38SStefano Zampini       partial_sum += j;
19503425bc38SStefano Zampini     }
19513425bc38SStefano Zampini   }
1952ef028eecSStefano Zampini   ierr = PetscFree(aux_global_numbering);CHKERRQ(ierr);
1953f0474715SStefano Zampini   ierr = PetscFree(aux_sums);CHKERRQ(ierr);
1954f0474715SStefano Zampini   ierr = PetscFree(aux_local_numbering_1);CHKERRQ(ierr);
1955f0474715SStefano Zampini   ierr = PetscFree(dual_dofs_boundary_indices);CHKERRQ(ierr);
19563425bc38SStefano Zampini   ierr = PetscFree(all_factors[0]);CHKERRQ(ierr);
19573425bc38SStefano Zampini   ierr = PetscFree(all_factors);CHKERRQ(ierr);
19583425bc38SStefano Zampini   /* printf("I found %d local lambda dofs when numbering them (should be %d)\n",partial_sum,n_local_lambda); */
1959f0474715SStefano Zampini 
1960f0474715SStefano Zampini   /* Local to global mapping of fetidpmat */
1961f0474715SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
1962f0474715SStefano Zampini   ierr = VecSetSizes(fetidpmat_ctx->lambda_local,n_local_lambda,n_local_lambda);CHKERRQ(ierr);
1963f0474715SStefano Zampini   ierr = VecSetType(fetidpmat_ctx->lambda_local,VECSEQ);CHKERRQ(ierr);
1964f0474715SStefano Zampini   ierr = VecCreate(comm,&lambda_global);CHKERRQ(ierr);
1965f0474715SStefano Zampini   ierr = VecSetSizes(lambda_global,PETSC_DECIDE,fetidpmat_ctx->n_lambda);CHKERRQ(ierr);
1966f0474715SStefano Zampini   ierr = VecSetType(lambda_global,VECMPI);CHKERRQ(ierr);
19673425bc38SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_lambda,l2g_indices,PETSC_OWN_POINTER,&IS_l2g_lambda);CHKERRQ(ierr);
19683425bc38SStefano Zampini   ierr = VecScatterCreate(fetidpmat_ctx->lambda_local,(IS)0,lambda_global,IS_l2g_lambda,&fetidpmat_ctx->l2g_lambda);CHKERRQ(ierr);
1969f0474715SStefano Zampini   ierr = ISDestroy(&IS_l2g_lambda);CHKERRQ(ierr);
19703425bc38SStefano Zampini 
19713425bc38SStefano Zampini   /* Create local part of B_delta */
19723425bc38SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&fetidpmat_ctx->B_delta);
19733425bc38SStefano Zampini   ierr = MatSetSizes(fetidpmat_ctx->B_delta,n_local_lambda,pcis->n_B,n_local_lambda,pcis->n_B);CHKERRQ(ierr);
19743425bc38SStefano Zampini   ierr = MatSetType(fetidpmat_ctx->B_delta,MATSEQAIJ);CHKERRQ(ierr);
19753425bc38SStefano Zampini   ierr = MatSeqAIJSetPreallocation(fetidpmat_ctx->B_delta,1,PETSC_NULL);CHKERRQ(ierr);
19763425bc38SStefano Zampini   ierr = MatSetOption(fetidpmat_ctx->B_delta,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
19773425bc38SStefano Zampini   for (i=0;i<n_local_lambda;i++) {
19783425bc38SStefano Zampini     ierr = MatSetValue(fetidpmat_ctx->B_delta,i,cols_B_delta[i],vals_B_delta[i],INSERT_VALUES);CHKERRQ(ierr);
19793425bc38SStefano Zampini   }
1980f0474715SStefano Zampini   ierr = PetscFree(vals_B_delta);CHKERRQ(ierr);
19813425bc38SStefano Zampini   ierr = MatAssemblyBegin(fetidpmat_ctx->B_delta,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19823425bc38SStefano Zampini   ierr = MatAssemblyEnd  (fetidpmat_ctx->B_delta,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19833425bc38SStefano Zampini 
19843425bc38SStefano Zampini   if (fully_redundant) {
19853425bc38SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&ScalingMat);
19863425bc38SStefano Zampini     ierr = MatSetSizes(ScalingMat,n_local_lambda,n_local_lambda,n_local_lambda,n_local_lambda);CHKERRQ(ierr);
19873425bc38SStefano Zampini     ierr = MatSetType(ScalingMat,MATSEQAIJ);CHKERRQ(ierr);
19883425bc38SStefano Zampini     ierr = MatSeqAIJSetPreallocation(ScalingMat,1,PETSC_NULL);CHKERRQ(ierr);
19893425bc38SStefano Zampini     for (i=0;i<n_local_lambda;i++) {
19903425bc38SStefano Zampini       ierr = MatSetValue(ScalingMat,i,i,scaling_factors[i],INSERT_VALUES);CHKERRQ(ierr);
19913425bc38SStefano Zampini     }
19923425bc38SStefano Zampini     ierr = MatAssemblyBegin(ScalingMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19933425bc38SStefano Zampini     ierr = MatAssemblyEnd  (ScalingMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19943425bc38SStefano Zampini     ierr = MatMatMult(ScalingMat,fetidpmat_ctx->B_delta,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&fetidpmat_ctx->B_Ddelta);CHKERRQ(ierr);
19953425bc38SStefano Zampini     ierr = MatDestroy(&ScalingMat);CHKERRQ(ierr);
19963425bc38SStefano Zampini   } else {
19973425bc38SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&fetidpmat_ctx->B_Ddelta);
19983425bc38SStefano Zampini     ierr = MatSetSizes(fetidpmat_ctx->B_Ddelta,n_local_lambda,pcis->n_B,n_local_lambda,pcis->n_B);CHKERRQ(ierr);
19993425bc38SStefano Zampini     ierr = MatSetType(fetidpmat_ctx->B_Ddelta,MATSEQAIJ);CHKERRQ(ierr);
20003425bc38SStefano Zampini     ierr = MatSeqAIJSetPreallocation(fetidpmat_ctx->B_Ddelta,1,PETSC_NULL);CHKERRQ(ierr);
20013425bc38SStefano Zampini     for (i=0;i<n_local_lambda;i++) {
20023425bc38SStefano Zampini       ierr = MatSetValue(fetidpmat_ctx->B_Ddelta,i,cols_B_delta[i],scaling_factors[i],INSERT_VALUES);CHKERRQ(ierr);
20033425bc38SStefano Zampini     }
20043425bc38SStefano Zampini     ierr = MatAssemblyBegin(fetidpmat_ctx->B_Ddelta,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20053425bc38SStefano Zampini     ierr = MatAssemblyEnd  (fetidpmat_ctx->B_Ddelta,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20063425bc38SStefano Zampini   }
2007f0474715SStefano Zampini   ierr = PetscFree(scaling_factors);CHKERRQ(ierr);
2008f0474715SStefano Zampini   ierr = PetscFree(cols_B_delta);CHKERRQ(ierr);
20093425bc38SStefano Zampini 
20103425bc38SStefano Zampini   /* Create some vectors needed by fetidp */
20113425bc38SStefano Zampini   ierr = VecDuplicate(pcis->vec1_B,&fetidpmat_ctx->temp_solution_B);CHKERRQ(ierr);
20123425bc38SStefano Zampini   ierr = VecDuplicate(pcis->vec1_D,&fetidpmat_ctx->temp_solution_D);CHKERRQ(ierr);
20133425bc38SStefano Zampini 
20143425bc38SStefano Zampini   test_fetidp = PETSC_FALSE;
20153425bc38SStefano Zampini   ierr = PetscOptionsGetBool(PETSC_NULL,"-fetidp_check",&test_fetidp,PETSC_NULL);CHKERRQ(ierr);
20163425bc38SStefano Zampini 
20173425bc38SStefano Zampini   if (test_fetidp) {
20183425bc38SStefano Zampini 
20193425bc38SStefano Zampini     ierr = PetscViewerASCIIGetStdout(((PetscObject)(fetidpmat_ctx->pc))->comm,&viewer);CHKERRQ(ierr);
20203425bc38SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
20213425bc38SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"----------FETI_DP TESTS--------------\n");CHKERRQ(ierr);
20223425bc38SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"All tests should return zero!\n");CHKERRQ(ierr);
20233425bc38SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"FETIDP MAT context in the ");CHKERRQ(ierr);
20243425bc38SStefano Zampini     if (fully_redundant) {
20253425bc38SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"fully redundant case for lagrange multipliers.\n");CHKERRQ(ierr);
20263425bc38SStefano Zampini     } else {
20273425bc38SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Non-fully redundant case for lagrange multiplier.\n");CHKERRQ(ierr);
20283425bc38SStefano Zampini     }
20293425bc38SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20303425bc38SStefano Zampini 
20313425bc38SStefano Zampini     /* TEST A/B: Test numbering of global lambda dofs             */
20323425bc38SStefano Zampini 
20333425bc38SStefano Zampini     ierr = VecDuplicate(fetidpmat_ctx->lambda_local,&test_vec);CHKERRQ(ierr);
20343425bc38SStefano Zampini     ierr = VecSet(lambda_global,1.0);CHKERRQ(ierr);
20353425bc38SStefano Zampini     ierr = VecSet(test_vec,1.0);CHKERRQ(ierr);
20363425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20373425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20383425bc38SStefano Zampini     scalar_value = -1.0;
20393425bc38SStefano Zampini     ierr = VecAXPY(test_vec,scalar_value,fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
20403425bc38SStefano Zampini     ierr = VecNorm(test_vec,NORM_INFINITY,&scalar_value);CHKERRQ(ierr);
20413425bc38SStefano Zampini     ierr = VecDestroy(&test_vec);CHKERRQ(ierr);
20423425bc38SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"A[%04d]: CHECK glob to loc: % 1.14e\n",rank,scalar_value);CHKERRQ(ierr);
20433425bc38SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20443425bc38SStefano Zampini     if (fully_redundant) {
20453425bc38SStefano Zampini       ierr = VecSet(lambda_global,0.0);CHKERRQ(ierr);
20463425bc38SStefano Zampini       ierr = VecSet(fetidpmat_ctx->lambda_local,0.5);CHKERRQ(ierr);
20473425bc38SStefano Zampini       ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20483425bc38SStefano Zampini       ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20493425bc38SStefano Zampini       ierr = VecSum(lambda_global,&scalar_value);CHKERRQ(ierr);
20503425bc38SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"B[%04d]: CHECK loc to glob: % 1.14e\n",rank,scalar_value-fetidpmat_ctx->n_lambda);CHKERRQ(ierr);
20513425bc38SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20523425bc38SStefano Zampini     }
20533425bc38SStefano Zampini 
20543425bc38SStefano Zampini     /* TEST C: It should holds B_delta*w=0, w\in\widehat{W}           */
20553425bc38SStefano Zampini     /* This is the meaning of the B matrix                            */
20563425bc38SStefano Zampini 
20573425bc38SStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,PETSC_NULL);CHKERRQ(ierr);
20583425bc38SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
20593425bc38SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20603425bc38SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20613425bc38SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20623425bc38SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20633425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20643425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20653425bc38SStefano Zampini     /* Action of B_delta */
20663425bc38SStefano Zampini     ierr = MatMult(fetidpmat_ctx->B_delta,pcis->vec1_B,fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
20673425bc38SStefano Zampini     ierr = VecSet(lambda_global,0.0);CHKERRQ(ierr);
20683425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20693425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20703425bc38SStefano Zampini     ierr = VecNorm(lambda_global,NORM_INFINITY,&scalar_value);CHKERRQ(ierr);
20713425bc38SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"C[coll]: CHECK infty norm of B_delta*w (w continuous): % 1.14e\n",scalar_value);CHKERRQ(ierr);
20723425bc38SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20733425bc38SStefano Zampini 
20743425bc38SStefano Zampini     /* TEST D: It should holds E_Dw = w - P_Dw w\in\widetilde{W}     */
20753425bc38SStefano Zampini     /* E_D = R_D^TR                                                   */
20763425bc38SStefano Zampini     /* P_D = B_{D,delta}^T B_{delta}                                  */
20773425bc38SStefano Zampini     /* eq.44 Mandel Tezaur and Dohrmann 2005                          */
20783425bc38SStefano Zampini 
20793425bc38SStefano Zampini     /* compute a random vector in \widetilde{W} */
20803425bc38SStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,PETSC_NULL);CHKERRQ(ierr);
20813425bc38SStefano Zampini     scalar_value = 0.0;  /* set zero at vertices */
20823425bc38SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20833425bc38SStefano Zampini     for (i=0;i<n_vertices;i++) { array[vertex_indices[i]]=scalar_value; }
20843425bc38SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
20853425bc38SStefano Zampini     /* store w for final comparison */
20863425bc38SStefano Zampini     ierr = VecDuplicate(pcis->vec1_B,&test_vec);CHKERRQ(ierr);
20873425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,test_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20883425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,test_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20893425bc38SStefano Zampini 
20903425bc38SStefano Zampini     /* Jump operator P_D : results stored in pcis->vec1_B */
20913425bc38SStefano Zampini 
20923425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20933425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20943425bc38SStefano Zampini     /* Action of B_delta */
20953425bc38SStefano Zampini     ierr = MatMult(fetidpmat_ctx->B_delta,pcis->vec1_B,fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
20963425bc38SStefano Zampini     ierr = VecSet(lambda_global,0.0);CHKERRQ(ierr);
20973425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20983425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20993425bc38SStefano Zampini     /* Action of B_Ddelta^T */
21003425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21013425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21023425bc38SStefano Zampini     ierr = MatMultTranspose(fetidpmat_ctx->B_Ddelta,fetidpmat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
21033425bc38SStefano Zampini 
21043425bc38SStefano Zampini     /* Average operator E_D : results stored in pcis->vec2_B */
21053425bc38SStefano Zampini 
21063425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21073425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21083425bc38SStefano Zampini     ierr = VecPointwiseMult(pcis->vec2_B,pcis->D,pcis->vec2_B);CHKERRQ(ierr);
21093425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21103425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec2_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21113425bc38SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
21123425bc38SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21133425bc38SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21143425bc38SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21153425bc38SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21163425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21173425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21183425bc38SStefano Zampini 
21193425bc38SStefano Zampini     /* test E_D=I-P_D */
21203425bc38SStefano Zampini     scalar_value = 1.0;
21213425bc38SStefano Zampini     ierr = VecAXPY(pcis->vec1_B,scalar_value,pcis->vec2_B);CHKERRQ(ierr);
21223425bc38SStefano Zampini     scalar_value = -1.0;
21233425bc38SStefano Zampini     ierr = VecAXPY(pcis->vec1_B,scalar_value,test_vec);CHKERRQ(ierr);
21243425bc38SStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&scalar_value);CHKERRQ(ierr);
21253425bc38SStefano Zampini     ierr = VecDestroy(&test_vec);CHKERRQ(ierr);
21263425bc38SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"D[%04d] CHECK infty norm of E_D + P_D - I: % 1.14e\n",rank,scalar_value);CHKERRQ(ierr);
21273425bc38SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21283425bc38SStefano Zampini 
21293425bc38SStefano Zampini     /* TEST E: It should holds R_D^TP_Dw=0 w\in\widetilde{W}          */
21303425bc38SStefano Zampini     /* eq.48 Mandel Tezaur and Dohrmann 2005                          */
21313425bc38SStefano Zampini 
21323425bc38SStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,PETSC_NULL);CHKERRQ(ierr);
21333425bc38SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
21343425bc38SStefano Zampini     scalar_value = 0.0;  /* set zero at vertices */
21353425bc38SStefano Zampini     for (i=0;i<n_vertices;i++) { array[vertex_indices[i]]=scalar_value; }
21363425bc38SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
21373425bc38SStefano Zampini 
21383425bc38SStefano Zampini     /* Jump operator P_D : results stored in pcis->vec1_B */
21393425bc38SStefano Zampini 
21403425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21413425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21423425bc38SStefano Zampini     /* Action of B_delta */
21433425bc38SStefano Zampini     ierr = MatMult(fetidpmat_ctx->B_delta,pcis->vec1_B,fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
21443425bc38SStefano Zampini     ierr = VecSet(lambda_global,0.0);CHKERRQ(ierr);
21453425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21463425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,lambda_global,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21473425bc38SStefano Zampini     /* Action of B_Ddelta^T */
21483425bc38SStefano Zampini     ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21493425bc38SStefano Zampini     ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21503425bc38SStefano Zampini     ierr = MatMultTranspose(fetidpmat_ctx->B_Ddelta,fetidpmat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
21513425bc38SStefano Zampini     /* diagonal scaling */
21523425bc38SStefano Zampini     ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
21533425bc38SStefano Zampini     /* sum on the interface */
21543425bc38SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
21553425bc38SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21563425bc38SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21573425bc38SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
21583425bc38SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21593425bc38SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21603425bc38SStefano Zampini     ierr = VecNorm(pcis->vec1_global,NORM_INFINITY,&scalar_value);CHKERRQ(ierr);
21613425bc38SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"E[coll]: CHECK infty norm of R^T_D P_D: % 1.14e\n",scalar_value);CHKERRQ(ierr);
21623425bc38SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21633425bc38SStefano Zampini 
21643425bc38SStefano Zampini     if (!fully_redundant) {
21653425bc38SStefano Zampini       /* TEST F: It should holds B_{delta}B^T_{D,delta}=I               */
21663425bc38SStefano Zampini       /* Corollary thm 14 Mandel Tezaur and Dohrmann 2005               */
21673425bc38SStefano Zampini       ierr = VecDuplicate(lambda_global,&test_vec);CHKERRQ(ierr);
21683425bc38SStefano Zampini       ierr = VecSetRandom(lambda_global,PETSC_NULL);CHKERRQ(ierr);
21693425bc38SStefano Zampini       /* Action of B_Ddelta^T */
21703425bc38SStefano Zampini       ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21713425bc38SStefano Zampini       ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,lambda_global,fetidpmat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21723425bc38SStefano Zampini       ierr = MatMultTranspose(fetidpmat_ctx->B_Ddelta,fetidpmat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
21733425bc38SStefano Zampini       /* Action of B_delta */
21743425bc38SStefano Zampini       ierr = MatMult(fetidpmat_ctx->B_delta,pcis->vec1_B,fetidpmat_ctx->lambda_local);CHKERRQ(ierr);
21753425bc38SStefano Zampini       ierr = VecSet(test_vec,0.0);CHKERRQ(ierr);
21763425bc38SStefano Zampini       ierr = VecScatterBegin(fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,test_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21773425bc38SStefano Zampini       ierr = VecScatterEnd  (fetidpmat_ctx->l2g_lambda,fetidpmat_ctx->lambda_local,test_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
21783425bc38SStefano Zampini       scalar_value = -1.0;
21793425bc38SStefano Zampini       ierr = VecAXPY(lambda_global,scalar_value,test_vec);CHKERRQ(ierr);
21803425bc38SStefano Zampini       ierr = VecNorm(lambda_global,NORM_INFINITY,&scalar_value);CHKERRQ(ierr);
21813425bc38SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"E[coll]: CHECK infty norm of P^T_D - I: % 1.14e\n",scalar_value);CHKERRQ(ierr);
21823425bc38SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21833425bc38SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21843425bc38SStefano Zampini       ierr = VecDestroy(&test_vec);CHKERRQ(ierr);
21853425bc38SStefano Zampini     }
21863425bc38SStefano Zampini   }
21873425bc38SStefano Zampini   /* final cleanup */
21883425bc38SStefano Zampini   ierr = PetscFree(vertex_indices);CHKERRQ(ierr);
21893425bc38SStefano Zampini   ierr = VecDestroy(&lambda_global);CHKERRQ(ierr);
21903425bc38SStefano Zampini 
21913425bc38SStefano Zampini   PetscFunctionReturn(0);
21923425bc38SStefano Zampini }
21933425bc38SStefano Zampini 
21943425bc38SStefano Zampini #undef __FUNCT__
21953425bc38SStefano Zampini #define __FUNCT__ "PCBDDCSetupFETIDPPCContext"
21963425bc38SStefano Zampini static PetscErrorCode PCBDDCSetupFETIDPPCContext(Mat fetimat, FETIDPPC_ctx *fetidppc_ctx)
21973425bc38SStefano Zampini {
21983425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
21993425bc38SStefano Zampini   PetscErrorCode ierr;
22003425bc38SStefano Zampini 
22013425bc38SStefano Zampini   PetscFunctionBegin;
22023425bc38SStefano Zampini   ierr = MatShellGetContext(fetimat,&mat_ctx);CHKERRQ(ierr);
22033425bc38SStefano Zampini   /* get references from objects created when setting up feti mat context */
22043425bc38SStefano Zampini   ierr = PetscObjectReference((PetscObject)mat_ctx->lambda_local);CHKERRQ(ierr);
22053425bc38SStefano Zampini   fetidppc_ctx->lambda_local = mat_ctx->lambda_local;
22063425bc38SStefano Zampini   ierr = PetscObjectReference((PetscObject)mat_ctx->B_Ddelta);CHKERRQ(ierr);
22073425bc38SStefano Zampini   fetidppc_ctx->B_Ddelta = mat_ctx->B_Ddelta;
22083425bc38SStefano Zampini   ierr = PetscObjectReference((PetscObject)mat_ctx->l2g_lambda);CHKERRQ(ierr);
22093425bc38SStefano Zampini   fetidppc_ctx->l2g_lambda = mat_ctx->l2g_lambda;
22103425bc38SStefano Zampini   PetscFunctionReturn(0);
22113425bc38SStefano Zampini }
22123425bc38SStefano Zampini 
22133425bc38SStefano Zampini #undef __FUNCT__
22143425bc38SStefano Zampini #define __FUNCT__ "FETIDPMatMult"
22153425bc38SStefano Zampini static PetscErrorCode FETIDPMatMult(Mat fetimat, Vec x, Vec y)
22163425bc38SStefano Zampini {
22173425bc38SStefano Zampini   FETIDPMat_ctx  *mat_ctx;
22183425bc38SStefano Zampini   PC_IS          *pcis;
22193425bc38SStefano Zampini   PetscErrorCode ierr;
22203425bc38SStefano Zampini 
22213425bc38SStefano Zampini   PetscFunctionBegin;
22223425bc38SStefano Zampini   ierr = MatShellGetContext(fetimat,&mat_ctx);CHKERRQ(ierr);
22233425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22243425bc38SStefano Zampini   /* Application of B_delta^T */
22253425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,x,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22263425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,x,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22273425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
22283425bc38SStefano Zampini   /* Application of \widetilde{S}^-1 */
22293425bc38SStefano Zampini   ierr = VecSet(pcis->vec1_D,0.0);CHKERRQ(ierr);
22303425bc38SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr);
22313425bc38SStefano Zampini   /* Application of B_delta */
22323425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
22333425bc38SStefano Zampini   ierr = VecSet(y,0.0);CHKERRQ(ierr);
22343425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22353425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22363425bc38SStefano Zampini   PetscFunctionReturn(0);
22373425bc38SStefano Zampini }
22383425bc38SStefano Zampini 
22393425bc38SStefano Zampini #undef __FUNCT__
22403425bc38SStefano Zampini #define __FUNCT__ "FETIDPPCApply"
22413425bc38SStefano Zampini static PetscErrorCode FETIDPPCApply(PC fetipc, Vec x, Vec y)
22423425bc38SStefano Zampini {
22433425bc38SStefano Zampini   FETIDPPC_ctx   *pc_ctx;
22443425bc38SStefano Zampini   PC_IS          *pcis;
22453425bc38SStefano Zampini   PetscErrorCode ierr;
22463425bc38SStefano Zampini 
22473425bc38SStefano Zampini   PetscFunctionBegin;
22483425bc38SStefano Zampini   ierr = PCShellGetContext(fetipc,(void**)&pc_ctx);
22493425bc38SStefano Zampini   pcis = (PC_IS*)pc_ctx->pc->data;
22503425bc38SStefano Zampini   /* Application of B_Ddelta^T */
22513425bc38SStefano Zampini   ierr = VecScatterBegin(pc_ctx->l2g_lambda,x,pc_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22523425bc38SStefano Zampini   ierr = VecScatterEnd(pc_ctx->l2g_lambda,x,pc_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22533425bc38SStefano Zampini   ierr = VecSet(pcis->vec2_B,0.0);CHKERRQ(ierr);
22543425bc38SStefano Zampini   ierr = MatMultTranspose(pc_ctx->B_Ddelta,pc_ctx->lambda_local,pcis->vec2_B);CHKERRQ(ierr);
22553425bc38SStefano Zampini   /* Application of S */
22563425bc38SStefano Zampini   ierr = PCISApplySchur(pc_ctx->pc,pcis->vec2_B,pcis->vec1_B,(Vec)0,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
22573425bc38SStefano Zampini   /* Application of B_Ddelta */
22583425bc38SStefano Zampini   ierr = MatMult(pc_ctx->B_Ddelta,pcis->vec1_B,pc_ctx->lambda_local);CHKERRQ(ierr);
22593425bc38SStefano Zampini   ierr = VecSet(y,0.0);CHKERRQ(ierr);
22603425bc38SStefano Zampini   ierr = VecScatterBegin(pc_ctx->l2g_lambda,pc_ctx->lambda_local,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22613425bc38SStefano Zampini   ierr = VecScatterEnd(pc_ctx->l2g_lambda,pc_ctx->lambda_local,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22623425bc38SStefano Zampini   PetscFunctionReturn(0);
22633425bc38SStefano Zampini }
22643425bc38SStefano Zampini 
2265da1bb401SStefano Zampini #undef __FUNCT__
2266da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetupLocalAdjacencyGraph"
2267da1bb401SStefano Zampini static PetscErrorCode PCBDDCSetupLocalAdjacencyGraph(PC pc)
2268da1bb401SStefano Zampini {
2269da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2270da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
22711a83f524SJed Brown   PetscInt       nvtxs;
22721a83f524SJed Brown   const PetscInt *xadj,*adjncy;
2273da1bb401SStefano Zampini   Mat            mat_adj;
2274da1bb401SStefano Zampini   PetscBool      symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE,flg_row=PETSC_TRUE;
2275da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
2276da1bb401SStefano Zampini   PetscErrorCode ierr;
2277da1bb401SStefano Zampini 
2278da1bb401SStefano Zampini   PetscFunctionBegin;
2279da1bb401SStefano Zampini   /* get CSR adjacency from local matrix if user has not yet provided local graph using PCBDDCSetLocalAdjacencyGraph function */
2280da1bb401SStefano Zampini   if (!mat_graph->xadj) {
2281da1bb401SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2282da1bb401SStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2283acee19a7SJed Brown     if (!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ()\n");
2284da1bb401SStefano Zampini     /* Get adjacency into BDDC workspace */
2285da1bb401SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
2286da1bb401SStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2287acee19a7SJed Brown     if (!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ()\n");
2288da1bb401SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2289da1bb401SStefano Zampini   }
2290da1bb401SStefano Zampini   PetscFunctionReturn(0);
2291da1bb401SStefano Zampini }
2292da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
22930c7d97c5SJed Brown #undef __FUNCT__
22940c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
22952617d88aSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc)
22960c7d97c5SJed Brown {
22970c7d97c5SJed Brown   PetscErrorCode    ierr;
22980c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)(pc->data);
22990c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
23003b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
23010c7d97c5SJed Brown 
23020c7d97c5SJed Brown   PetscFunctionBegin;
23030c7d97c5SJed Brown   /* Application of PHI^T  */
23040c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
230529622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
23060c7d97c5SJed Brown 
23070c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
2308142dfd88SStefano Zampini   if (pcbddc->coarse_rhs) { ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr); }
23090c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23100c7d97c5SJed Brown 
23110c7d97c5SJed Brown   /* Local solution on R nodes */
23120c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
23130c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23140c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
231529622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
23160c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23170c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23180c7d97c5SJed Brown   }
23190c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
23200c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
23210c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23220c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232329622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) {
23240c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23250c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23260c7d97c5SJed Brown   }
23270c7d97c5SJed Brown 
23280c7d97c5SJed Brown   /* Coarse solution */
23290c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23300bdf917eSStefano Zampini   if (pcbddc->coarse_rhs) {
23310bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) {
23320bdf917eSStefano Zampini       ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
23330bdf917eSStefano Zampini     }
23340bdf917eSStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
23350bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) {
23360bdf917eSStefano Zampini       ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,pcbddc->coarse_vec,PETSC_NULL);CHKERRQ(ierr);
23370bdf917eSStefano Zampini     }
23380bdf917eSStefano Zampini   }
23390c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23400c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23410c7d97c5SJed Brown 
23420c7d97c5SJed Brown   /* Sum contributions from two levels */
23430c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
234429622bf0SStefano Zampini   if (pcbddc->inexact_prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
23450c7d97c5SJed Brown   PetscFunctionReturn(0);
23460c7d97c5SJed Brown }
23470c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
23480c7d97c5SJed Brown #undef __FUNCT__
23490c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
235053cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
23510c7d97c5SJed Brown {
23520c7d97c5SJed Brown   PetscErrorCode ierr;
23530c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
23540c7d97c5SJed Brown 
23550c7d97c5SJed Brown   PetscFunctionBegin;
235653cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2357534831adSStefano Zampini   if (pcbddc->local_auxmat1) {
23580c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
23590c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
23600c7d97c5SJed Brown   }
23610c7d97c5SJed Brown   PetscFunctionReturn(0);
23620c7d97c5SJed Brown }
23630c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
23640c7d97c5SJed Brown #undef __FUNCT__
23650c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
236653cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
23670c7d97c5SJed Brown {
23680c7d97c5SJed Brown   PetscErrorCode ierr;
23690c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
23700c7d97c5SJed Brown 
23710c7d97c5SJed Brown   PetscFunctionBegin;
23720c7d97c5SJed Brown   switch (pcbddc->coarse_communications_type) {
23730c7d97c5SJed Brown     case SCATTERS_BDDC:
23740c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
23750c7d97c5SJed Brown       break;
23760c7d97c5SJed Brown     case GATHERS_BDDC:
23770c7d97c5SJed Brown       break;
23780c7d97c5SJed Brown   }
23790c7d97c5SJed Brown   PetscFunctionReturn(0);
23800c7d97c5SJed Brown }
23810c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
23820c7d97c5SJed Brown #undef __FUNCT__
23830c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
238453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
23850c7d97c5SJed Brown {
23860c7d97c5SJed Brown   PetscErrorCode ierr;
23870c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
23880c7d97c5SJed Brown   PetscScalar*   array_to;
23890c7d97c5SJed Brown   PetscScalar*   array_from;
23900c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
23910c7d97c5SJed Brown   PetscInt       i;
23920c7d97c5SJed Brown 
23930c7d97c5SJed Brown   PetscFunctionBegin;
23940c7d97c5SJed Brown   switch (pcbddc->coarse_communications_type) {
23950c7d97c5SJed Brown     case SCATTERS_BDDC:
23960c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
23970c7d97c5SJed Brown       break;
23980c7d97c5SJed Brown     case GATHERS_BDDC:
23990c7d97c5SJed Brown       if (vec_from) VecGetArray(vec_from,&array_from);
24000c7d97c5SJed Brown       if (vec_to)   VecGetArray(vec_to,&array_to);
24010c7d97c5SJed Brown       switch (pcbddc->coarse_problem_type) {
24020c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
24030c7d97c5SJed Brown           if (smode == SCATTER_FORWARD) {
240453cdbc3dSStefano Zampini             ierr = MPI_Gatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
24050c7d97c5SJed Brown             if (vec_to) {
24060bdf917eSStefano Zampini               if (imode == ADD_VALUES) {
24070bdf917eSStefano Zampini                 for (i=0;i<pcbddc->replicated_primal_size;i++) {
24080c7d97c5SJed Brown                   array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
24090c7d97c5SJed Brown                 }
24100c7d97c5SJed Brown               } else {
24110bdf917eSStefano Zampini                 for (i=0;i<pcbddc->replicated_primal_size;i++) {
24120bdf917eSStefano Zampini                   array_to[pcbddc->replicated_local_primal_indices[i]]=pcbddc->replicated_local_primal_values[i];
24130bdf917eSStefano Zampini                 }
24140bdf917eSStefano Zampini               }
24150bdf917eSStefano Zampini             }
24160bdf917eSStefano Zampini           } else {
24170bdf917eSStefano Zampini             if (vec_from) {
24180bdf917eSStefano Zampini               if (imode == ADD_VALUES) {
24190bdf917eSStefano Zampini                 printf("Scatter mode %d, insert mode %d for case %d not implemented!\n",smode,imode,pcbddc->coarse_problem_type);
24200bdf917eSStefano Zampini               }
24210bdf917eSStefano Zampini               for (i=0;i<pcbddc->replicated_primal_size;i++) {
24220c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
24230bdf917eSStefano Zampini               }
24240bdf917eSStefano Zampini             }
242553cdbc3dSStefano Zampini             ierr = MPI_Scatterv(&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,&array_to[0],pcbddc->local_primal_size,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
24260c7d97c5SJed Brown           }
24270c7d97c5SJed Brown           break;
24280c7d97c5SJed Brown         case REPLICATED_BDDC:
24290c7d97c5SJed Brown           if (smode == SCATTER_FORWARD) {
243053cdbc3dSStefano Zampini             ierr = MPI_Allgatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,comm);CHKERRQ(ierr);
24310bdf917eSStefano Zampini             if (imode == ADD_VALUES) {
24320bdf917eSStefano Zampini               for (i=0;i<pcbddc->replicated_primal_size;i++) {
24330c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
24340bdf917eSStefano Zampini               }
24350bdf917eSStefano Zampini             } else {
24360bdf917eSStefano Zampini               for (i=0;i<pcbddc->replicated_primal_size;i++) {
24370bdf917eSStefano Zampini                 array_to[pcbddc->replicated_local_primal_indices[i]]=pcbddc->replicated_local_primal_values[i];
24380bdf917eSStefano Zampini               }
24390bdf917eSStefano Zampini             }
24400c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
24410bdf917eSStefano Zampini             if (imode == ADD_VALUES) {
24420bdf917eSStefano Zampini               for (i=0;i<pcbddc->local_primal_size;i++) {
24430bdf917eSStefano Zampini                 array_to[i]+=array_from[pcbddc->local_primal_indices[i]];
24440bdf917eSStefano Zampini               }
24450bdf917eSStefano Zampini             } else {
24460bdf917eSStefano Zampini               for (i=0;i<pcbddc->local_primal_size;i++) {
24470c7d97c5SJed Brown                 array_to[i]=array_from[pcbddc->local_primal_indices[i]];
24480c7d97c5SJed Brown               }
24490bdf917eSStefano Zampini             }
24500bdf917eSStefano Zampini           }
24510c7d97c5SJed Brown           break;
245253cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
245353cdbc3dSStefano Zampini           break;
245453cdbc3dSStefano Zampini         case PARALLEL_BDDC:
245553cdbc3dSStefano Zampini           break;
24560c7d97c5SJed Brown       }
24570c7d97c5SJed Brown       if (vec_from) VecRestoreArray(vec_from,&array_from);
24580c7d97c5SJed Brown       if (vec_to)   VecRestoreArray(vec_to,&array_to);
24590c7d97c5SJed Brown       break;
24600c7d97c5SJed Brown   }
24610c7d97c5SJed Brown   PetscFunctionReturn(0);
24620c7d97c5SJed Brown }
24630c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
24643b03a366Sstefano_zampini #undef __FUNCT__
24653b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
24663b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
24673b03a366Sstefano_zampini {
24683b03a366Sstefano_zampini   PetscErrorCode ierr;
24693b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
24703b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
24713b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
247223d4d1a5SStefano Zampini   PetscInt       *nnz,*is_indices;
24733b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
2474534831adSStefano Zampini   PetscInt       *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B,*local_to_B;
24753b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
24763b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
2477534831adSStefano Zampini   PetscScalar    quad_value;
24783b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
24793b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
24803b03a366Sstefano_zampini   IS             *used_IS;
248119fd82e9SBarry Smith   MatType        impMatType=MATSEQAIJ;
24823b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
24833b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
2484fcda91b4SJed Brown   MatNullSpace   nearnullsp;
2485fcda91b4SJed Brown   const Vec      *nearnullvecs;
24863b03a366Sstefano_zampini   Vec            *localnearnullsp;
24873b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
24883b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
2489534831adSStefano Zampini   PetscBLASInt   Bone=1,*ipiv;
2490534831adSStefano Zampini   Vec            temp_vec;
2491534831adSStefano Zampini   Mat            temp_mat;
2492534831adSStefano Zampini   KSP            temp_ksp;
2493ffe5efe1SStefano Zampini   PC             temp_pc;
2494534831adSStefano Zampini   PetscInt       s,start_constraint,dual_dofs;
2495534831adSStefano Zampini   PetscBool      compute_submatrix,useksp=PETSC_FALSE;
2496534831adSStefano Zampini   PetscInt       *aux_primal_permutation,*aux_primal_numbering;
2497534831adSStefano Zampini   PetscBool      boolforface,*change_basis;
2498de534f79Sstefano_zampini /* some ugly conditional declarations */
24993b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
25003b03a366Sstefano_zampini   PetscScalar    dot_result;
25013b03a366Sstefano_zampini   PetscScalar    one=1.0,zero=0.0;
25023b03a366Sstefano_zampini   PetscInt       ii;
25033425bc38SStefano Zampini   PetscScalar    *singular_vectors;
25043425bc38SStefano Zampini   PetscBLASInt   *iwork,*ifail;
25053425bc38SStefano Zampini   PetscReal      dummy_real,abs_tol;
25063425bc38SStefano Zampini   PetscBLASInt   eigs_found;
25073b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
25083b03a366Sstefano_zampini   PetscScalar    val1,val2;
25093b03a366Sstefano_zampini #endif
25103425bc38SStefano Zampini #endif
25113b03a366Sstefano_zampini   PetscBLASInt   dummy_int;
25123b03a366Sstefano_zampini   PetscScalar    dummy_scalar;
25133b03a366Sstefano_zampini 
25143b03a366Sstefano_zampini   PetscFunctionBegin;
25153b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
2516fcda91b4SJed Brown   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2517fcda91b4SJed Brown   if (nearnullsp) {
2518fcda91b4SJed Brown     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
25193b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
25203b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
25213b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
25223b03a366Sstefano_zampini   }
25233b03a366Sstefano_zampini   if (nnsp_has_cnst) {
25243b03a366Sstefano_zampini     nnsp_addone = 1;
25253b03a366Sstefano_zampini   }
25263b03a366Sstefano_zampini   /*
25273b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
25283b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
25293b03a366Sstefano_zampini        - temp_indices_to_constraint  [temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in local numbering) on which the constraint acts
2530534831adSStefano Zampini        - temp_indices_to_constraint_B[temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in boundary numbering) on which the constraint acts
25313b03a366Sstefano_zampini        - temp_quadrature_constraint  [temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
25323b03a366Sstefano_zampini                                                                                                                                                          */
2533da1bb401SStefano Zampini 
25343b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
25353b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
2536da1bb401SStefano Zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
2537da1bb401SStefano Zampini   total_counts += n_vertices;
25383b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
2539534831adSStefano Zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscBool),&change_basis);CHKERRQ(ierr);
25403b03a366Sstefano_zampini   total_counts = 0;
25413b03a366Sstefano_zampini   max_size_of_constraint = 0;
25423b03a366Sstefano_zampini   for (i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++) {
25433b03a366Sstefano_zampini     if (i<pcbddc->n_ISForEdges) {
25443b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
25453b03a366Sstefano_zampini     } else {
25463b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
25473b03a366Sstefano_zampini     }
25483b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
25493b03a366Sstefano_zampini     total_counts += j;
25503b03a366Sstefano_zampini     if (j>max_size_of_constraint) max_size_of_constraint=j;
25513b03a366Sstefano_zampini   }
25523b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
2553da1bb401SStefano Zampini   total_counts += n_vertices;
25543b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
25553b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
2556534831adSStefano Zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint_B);CHKERRQ(ierr);
2557534831adSStefano Zampini   ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&local_to_B);CHKERRQ(ierr);
2558534831adSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2559534831adSStefano Zampini   for (i=0;i<pcis->n;i++) {
2560534831adSStefano Zampini     local_to_B[i]=-1;
2561534831adSStefano Zampini   }
2562534831adSStefano Zampini   for (i=0;i<pcis->n_B;i++) {
2563534831adSStefano Zampini     local_to_B[is_indices[i]]=i;
2564534831adSStefano Zampini   }
2565534831adSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2566534831adSStefano Zampini 
25673b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
25683b03a366Sstefano_zampini   rwork = 0;
25693b03a366Sstefano_zampini   work = 0;
25703b03a366Sstefano_zampini   singular_vals = 0;
25713b03a366Sstefano_zampini   temp_basis = 0;
25723b03a366Sstefano_zampini   correlation_mat = 0;
25733b03a366Sstefano_zampini   if (!pcbddc->use_nnsp_true) {
25743b03a366Sstefano_zampini     PetscScalar temp_work;
25753b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
25763b03a366Sstefano_zampini     /* POD */
25773b03a366Sstefano_zampini     PetscInt max_n;
25783b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
25793b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
25803b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
25813425bc38SStefano Zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&singular_vectors);CHKERRQ(ierr);
25823b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
25833b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
25843b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
25853b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
25863b03a366Sstefano_zampini #endif
25873425bc38SStefano Zampini     ierr = PetscMalloc(5*max_n*sizeof(PetscBLASInt),&iwork);CHKERRQ(ierr);
25883425bc38SStefano Zampini     ierr = PetscMalloc(max_n*sizeof(PetscBLASInt),&ifail);CHKERRQ(ierr);
25893b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
2590*c5df96a5SBarry Smith     ierr  = PetscBLASIntCast(max_n,&Bt);CHKERRQ(ierr);
25913b03a366Sstefano_zampini     lwork =-1;
25923425bc38SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
25933b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
25943425bc38SStefano Zampini     abs_tol=1.e-8;
25953425bc38SStefano Zampini     LAPACKsyevx_("V","A","U",&Bt,correlation_mat,&Bt,&dummy_real,&dummy_real,&dummy_int,&dummy_int,
25963425bc38SStefano Zampini                  &abs_tol,&eigs_found,singular_vals,singular_vectors,&Bt,&temp_work,&lwork,iwork,ifail,&lierr);
25973b03a366Sstefano_zampini #else
25983425bc38SStefano Zampini     SETERRQ(((PetscObject) pc)->comm, PETSC_ERR_SUP, "Not yet implemented for complexes when PETSC_MISSING_GESVD = 1");
25993b03a366Sstefano_zampini #endif
26003425bc38SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEVX Lapack routine %d",(int)lierr);
26013425bc38SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
26023b03a366Sstefano_zampini #else /* on missing GESVD */
26033b03a366Sstefano_zampini     /* SVD */
26043b03a366Sstefano_zampini     PetscInt max_n,min_n;
26053b03a366Sstefano_zampini     max_n = max_size_of_constraint;
26063b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
26073b03a366Sstefano_zampini     if (max_size_of_constraint < (nnsp_addone+nnsp_size)) {
26083b03a366Sstefano_zampini       min_n = max_size_of_constraint;
26093b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
26103b03a366Sstefano_zampini     }
26113b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
26123b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
26133b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
26143b03a366Sstefano_zampini #endif
26153b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
26163b03a366Sstefano_zampini     lwork =-1;
2617*c5df96a5SBarry Smith     ierr  = PetscBLASIntCast(max_n,&Bs);CHKERRQ(ierr);
2618*c5df96a5SBarry Smith     ierr  = PetscBLASIntCast(min_n,&Bt);CHKERRQ(ierr);
26193b03a366Sstefano_zampini     dummy_int = Bs;
2620670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
26213b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
26223b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
26233b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
26243b03a366Sstefano_zampini #else
26253b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
26263b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
26273b03a366Sstefano_zampini #endif
26283b03a366Sstefano_zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
2629670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
26303b03a366Sstefano_zampini #endif
26313b03a366Sstefano_zampini     /* Allocate optimal workspace */
2632*c5df96a5SBarry Smith     ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
26333b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
26343b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
26353b03a366Sstefano_zampini   }
26363b03a366Sstefano_zampini   /* get local part of global near null space vectors */
26373b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
26383b03a366Sstefano_zampini   for (k=0;k<nnsp_size;k++) {
26393b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2640fcda91b4SJed Brown     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2641fcda91b4SJed Brown     ierr = VecScatterEnd  (matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
26423b03a366Sstefano_zampini   }
26433b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
26443b03a366Sstefano_zampini   total_counts=0;
26453b03a366Sstefano_zampini   temp_indices[0]=0;
2646da1bb401SStefano Zampini   /* vertices */
2647da1bb401SStefano Zampini   PetscBool used_vertex;
2648da1bb401SStefano Zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2649da1bb401SStefano Zampini   if (nnsp_has_cnst) { /* consider all vertices */
2650da1bb401SStefano Zampini     for (i=0;i<n_vertices;i++) {
2651da1bb401SStefano Zampini       temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
2652534831adSStefano Zampini       temp_indices_to_constraint_B[temp_indices[total_counts]]=local_to_B[is_indices[i]];
2653da1bb401SStefano Zampini       temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
2654da1bb401SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+1;
2655534831adSStefano Zampini       change_basis[total_counts]=PETSC_FALSE;
2656da1bb401SStefano Zampini       total_counts++;
2657da1bb401SStefano Zampini     }
2658da1bb401SStefano Zampini   } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
2659da1bb401SStefano Zampini     for (i=0;i<n_vertices;i++) {
2660da1bb401SStefano Zampini       used_vertex=PETSC_FALSE;
2661da1bb401SStefano Zampini       k=0;
2662da1bb401SStefano Zampini       while (!used_vertex && k<nnsp_size) {
2663da1bb401SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
2664da1bb401SStefano Zampini         if (PetscAbsScalar(array_vector[is_indices[i]])>0.0) {
2665da1bb401SStefano Zampini           temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
2666534831adSStefano Zampini           temp_indices_to_constraint_B[temp_indices[total_counts]]=local_to_B[is_indices[i]];
2667da1bb401SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
2668da1bb401SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+1;
2669534831adSStefano Zampini           change_basis[total_counts]=PETSC_FALSE;
2670da1bb401SStefano Zampini           total_counts++;
2671da1bb401SStefano Zampini           used_vertex=PETSC_TRUE;
2672da1bb401SStefano Zampini         }
2673da1bb401SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
2674da1bb401SStefano Zampini         k++;
2675da1bb401SStefano Zampini       }
2676da1bb401SStefano Zampini     }
2677da1bb401SStefano Zampini   }
2678da1bb401SStefano Zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2679da1bb401SStefano Zampini   n_vertices=total_counts;
2680da1bb401SStefano Zampini   /* edges and faces */
26813b03a366Sstefano_zampini   for (i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++) {
26823b03a366Sstefano_zampini     if (i<pcbddc->n_ISForEdges) {
26833b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
2684534831adSStefano Zampini       boolforface = pcbddc->usechangeofbasis;
26853b03a366Sstefano_zampini     } else {
26863b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
2687534831adSStefano Zampini       boolforface = pcbddc->usechangeonfaces;
26883b03a366Sstefano_zampini     }
26893b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
26903b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
26913b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
26923b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
26933b03a366Sstefano_zampini     if (nnsp_has_cnst) {
26943b03a366Sstefano_zampini       temp_constraints++;
2695534831adSStefano Zampini       quad_value = (PetscScalar) (1.0/PetscSqrtReal((PetscReal)size_of_constraint));
26963b03a366Sstefano_zampini       for (j=0;j<size_of_constraint;j++) {
26973b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
2698534831adSStefano Zampini         temp_indices_to_constraint_B[temp_indices[total_counts]+j]=local_to_B[is_indices[j]];
26993b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
27003b03a366Sstefano_zampini       }
27013b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
2702534831adSStefano Zampini       change_basis[total_counts]=boolforface;
27033b03a366Sstefano_zampini       total_counts++;
27043b03a366Sstefano_zampini     }
27053b03a366Sstefano_zampini     for (k=0;k<nnsp_size;k++) {
27063b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
27073b03a366Sstefano_zampini       for (j=0;j<size_of_constraint;j++) {
27083b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
2709534831adSStefano Zampini         temp_indices_to_constraint_B[temp_indices[total_counts]+j]=local_to_B[is_indices[j]];
27103b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
27113b03a366Sstefano_zampini       }
27123b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
2713de534f79Sstefano_zampini       quad_value = 1.0;
2714de534f79Sstefano_zampini       if (use_nnsp_true) { /* check if array is null on the connected component in case use_nnsp_true has been requested */
2715*c5df96a5SBarry Smith         ierr       = PetscBLASIntCast(size_of_constraint,&Bs);CHKERRQ(ierr);
2716de534f79Sstefano_zampini         quad_value = BLASasum_(&Bs,&temp_quadrature_constraint[temp_indices[total_counts]],&Bone);
2717de534f79Sstefano_zampini       }
2718de534f79Sstefano_zampini       if (quad_value > 0.0) { /* keep indices and values */
2719de534f79Sstefano_zampini         temp_constraints++;
27203b03a366Sstefano_zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
2721534831adSStefano Zampini         change_basis[total_counts]=boolforface;
27223b03a366Sstefano_zampini         total_counts++;
27233b03a366Sstefano_zampini       }
2724de534f79Sstefano_zampini     }
27253b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2726de534f79Sstefano_zampini     /* perform SVD on the constraint if use_nnsp_true has not be requested by the user */
27273b03a366Sstefano_zampini     if (!use_nnsp_true) {
2728*c5df96a5SBarry Smith       ierr = PetscBLASIntCast(size_of_constraint,&Bs);CHKERRQ(ierr);
2729*c5df96a5SBarry Smith       ierr = PetscBLASIntCast(temp_constraints,&Bt);CHKERRQ(ierr);
2730de534f79Sstefano_zampini 
27313b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
27323b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
27333b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
27343b03a366Sstefano_zampini       for (j=0;j<temp_constraints;j++) {
27353b03a366Sstefano_zampini         for (k=0;k<j+1;k++) {
27363b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
27373425bc38SStefano Zampini           /* hand made complex dot product -> replace */
27383b03a366Sstefano_zampini           dot_result = 0.0;
27393b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
27403b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
27413b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
27423b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
27433b03a366Sstefano_zampini           }
27443b03a366Sstefano_zampini #else
27453b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
27463b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
27473b03a366Sstefano_zampini #endif
27483b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
27493b03a366Sstefano_zampini         }
27503b03a366Sstefano_zampini       }
27513425bc38SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27523b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
27533425bc38SStefano Zampini /*      LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr); */
27543425bc38SStefano Zampini       LAPACKsyevx_("V","A","U",&Bt,correlation_mat,&Bt,&dummy_real,&dummy_real,&dummy_int,&dummy_int,
27553425bc38SStefano Zampini                  &abs_tol,&eigs_found,singular_vals,singular_vectors,&Bt,work,&lwork,iwork,ifail,&lierr);
27563b03a366Sstefano_zampini #else
27573425bc38SStefano Zampini /*  LAPACK call is missing here! TODO */
27583425bc38SStefano Zampini       SETERRQ(((PetscObject) pc)->comm, PETSC_ERR_SUP, "Not yet implemented for complexes when PETSC_MISSING_GESVD = 1");
27593b03a366Sstefano_zampini #endif
27603425bc38SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEVX Lapack routine %d",(int)lierr);
27613425bc38SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
27623b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
27633b03a366Sstefano_zampini       j=0;
27643b03a366Sstefano_zampini       while (j < Bt && singular_vals[j] < tol) j++;
27653b03a366Sstefano_zampini       total_counts=total_counts-j;
27663b03a366Sstefano_zampini       if (j<temp_constraints) {
27673b03a366Sstefano_zampini         for (k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
27683425bc38SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27693b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
27703425bc38SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
27713b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
27723b03a366Sstefano_zampini         for (k=0;k<Bt-j;k++) {
27733b03a366Sstefano_zampini           for (ii=0;ii<size_of_constraint;ii++) {
27743b03a366Sstefano_zampini             temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[Bt-1-k]*temp_basis[(Bt-1-k)*size_of_constraint+ii];
27753b03a366Sstefano_zampini           }
27763b03a366Sstefano_zampini         }
27773b03a366Sstefano_zampini       }
2778de534f79Sstefano_zampini 
27793b03a366Sstefano_zampini #else  /* on missing GESVD */
27803b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
27813b03a366Sstefano_zampini       if (min_n > size_of_constraint) min_n = size_of_constraint;
27823b03a366Sstefano_zampini       dummy_int = Bs;
2783670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27843b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
27853b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
27863b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
27873b03a366Sstefano_zampini #else
27883b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
27893b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
27903b03a366Sstefano_zampini #endif
27913b03a366Sstefano_zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
2792670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
27933b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
27943b03a366Sstefano_zampini       j=0;
27953b03a366Sstefano_zampini       while (j < min_n && singular_vals[min_n-j-1] < tol) j++;
27963b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
27973b03a366Sstefano_zampini #endif
27983b03a366Sstefano_zampini     }
27993b03a366Sstefano_zampini   }
2800534831adSStefano Zampini 
2801da1bb401SStefano Zampini   n_constraints=total_counts-n_vertices;
2802da1bb401SStefano Zampini   local_primal_size = total_counts;
28033b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
28043b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
28053b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
2806da1bb401SStefano Zampini   pcbddc->local_primal_size = local_primal_size;
2807534831adSStefano Zampini 
2808534831adSStefano Zampini   /* Create constraint matrix */
2809534831adSStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
2810534831adSStefano Zampini   /* so we need to set it up properly either with or without change of basis */
2811534831adSStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2812534831adSStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
2813534831adSStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
2814534831adSStefano Zampini   /* compute a local numbering of constraints : vertices first then constraints */
2815534831adSStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
2816534831adSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array_vector);CHKERRQ(ierr);
2817534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&aux_primal_numbering);CHKERRQ(ierr);
2818534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&aux_primal_permutation);CHKERRQ(ierr);
2819534831adSStefano Zampini   total_counts=0;
2820534831adSStefano Zampini   /* find vertices: subdomain corners plus dofs with basis changed */
2821534831adSStefano Zampini   for (i=0;i<local_primal_size;i++) {
2822534831adSStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
2823534831adSStefano Zampini     if (change_basis[i] || size_of_constraint == 1) {
2824534831adSStefano Zampini       k=0;
2825534831adSStefano Zampini       while (k < size_of_constraint && array_vector[temp_indices_to_constraint[temp_indices[i]+size_of_constraint-k-1]] != 0.0) {
2826534831adSStefano Zampini         k=k+1;
2827534831adSStefano Zampini       }
2828534831adSStefano Zampini       j=temp_indices_to_constraint[temp_indices[i]+size_of_constraint-k-1];
2829534831adSStefano Zampini       array_vector[j] = 1.0;
2830534831adSStefano Zampini       aux_primal_numbering[total_counts]=j;
2831534831adSStefano Zampini       aux_primal_permutation[total_counts]=total_counts;
2832534831adSStefano Zampini       total_counts++;
2833534831adSStefano Zampini     }
2834534831adSStefano Zampini   }
2835534831adSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array_vector);CHKERRQ(ierr);
2836534831adSStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2837534831adSStefano Zampini   ierr = PetscSortIntWithPermutation(total_counts,aux_primal_numbering,aux_primal_permutation);
2838534831adSStefano Zampini   /* nonzero structure */
2839534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
2840534831adSStefano Zampini   for (i=0;i<total_counts;i++) {
2841534831adSStefano Zampini     nnz[i]=1;
2842534831adSStefano Zampini   }
2843534831adSStefano Zampini   j=total_counts;
2844534831adSStefano Zampini   for (i=n_vertices;i<local_primal_size;i++) {
2845534831adSStefano Zampini     if (!change_basis[i]) {
2846534831adSStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2847534831adSStefano Zampini       j++;
2848534831adSStefano Zampini     }
2849534831adSStefano Zampini   }
2850534831adSStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2851534831adSStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2852534831adSStefano Zampini   /* set values in constraint matrix */
2853534831adSStefano Zampini   for (i=0;i<total_counts;i++) {
2854534831adSStefano Zampini     j = aux_primal_permutation[i];
2855534831adSStefano Zampini     k = aux_primal_numbering[j];
2856534831adSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,k,1.0,INSERT_VALUES);CHKERRQ(ierr);
2857534831adSStefano Zampini   }
2858534831adSStefano Zampini   for (i=n_vertices;i<local_primal_size;i++) {
2859534831adSStefano Zampini     if (!change_basis[i]) {
2860534831adSStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2861534831adSStefano Zampini       ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&total_counts,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
2862534831adSStefano Zampini       total_counts++;
2863534831adSStefano Zampini     }
2864534831adSStefano Zampini   }
2865534831adSStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2866534831adSStefano Zampini   ierr = PetscFree(aux_primal_permutation);CHKERRQ(ierr);
2867534831adSStefano Zampini   /* assembling */
2868534831adSStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2869534831adSStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2870534831adSStefano Zampini 
2871534831adSStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->usechangeofbasis is FALSE */
2872534831adSStefano Zampini   if (pcbddc->usechangeofbasis) {
2873534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2874534831adSStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2875534831adSStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2876534831adSStefano Zampini     /* work arrays */
2877534831adSStefano Zampini     /* we need to reuse these arrays, so we free them */
2878534831adSStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2879534831adSStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
2880534831adSStefano Zampini     ierr = PetscMalloc(pcis->n_B*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
2881534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
2882534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*sizeof(PetscScalar),&work);CHKERRQ(ierr);
2883534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*sizeof(PetscBLASInt),&ipiv);CHKERRQ(ierr);
2884534831adSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2885534831adSStefano Zampini       nnz[i]=1;
2886534831adSStefano Zampini     }
2887534831adSStefano Zampini     /* Overestimated nonzeros per row */
2888534831adSStefano Zampini     k=1;
2889534831adSStefano Zampini     for (i=pcbddc->n_vertices;i<local_primal_size;i++) {
2890534831adSStefano Zampini       if (change_basis[i]) {
2891534831adSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2892534831adSStefano Zampini         if (k < size_of_constraint) {
2893534831adSStefano Zampini           k = size_of_constraint;
2894534831adSStefano Zampini         }
2895534831adSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
2896534831adSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2897534831adSStefano Zampini         }
2898534831adSStefano Zampini       }
2899534831adSStefano Zampini     }
2900534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2901534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2902534831adSStefano Zampini     /* Temporary array to store indices */
2903534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&is_indices);CHKERRQ(ierr);
2904534831adSStefano Zampini     /* Set initial identity in the matrix */
2905534831adSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2906534831adSStefano Zampini       ierr = MatSetValue(pcbddc->ChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2907534831adSStefano Zampini     }
2908534831adSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2909534831adSStefano Zampini     /* Change of basis matrix is evaluated as the FIRST APPROACH in */
2910534831adSStefano Zampini     /* Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (6.2.1) */
2911534831adSStefano Zampini     temp_constraints = 0;
291293dc3b60SStefano Zampini     if (pcbddc->n_vertices < local_primal_size) {
2913534831adSStefano Zampini       temp_start_ptr = temp_indices_to_constraint_B[temp_indices[pcbddc->n_vertices]];
291493dc3b60SStefano Zampini     }
2915534831adSStefano Zampini     for (i=pcbddc->n_vertices;i<local_primal_size;i++) {
2916534831adSStefano Zampini       if (change_basis[i]) {
2917534831adSStefano Zampini         compute_submatrix = PETSC_FALSE;
2918534831adSStefano Zampini         useksp = PETSC_FALSE;
2919534831adSStefano Zampini         if (temp_start_ptr == temp_indices_to_constraint_B[temp_indices[i]]) {
2920534831adSStefano Zampini           temp_constraints++;
292104eaf177SStefano Zampini           if (i == local_primal_size -1 ||  temp_start_ptr != temp_indices_to_constraint_B[temp_indices[i+1]]) {
2922534831adSStefano Zampini             compute_submatrix = PETSC_TRUE;
2923534831adSStefano Zampini           }
2924534831adSStefano Zampini         }
2925534831adSStefano Zampini         if (compute_submatrix) {
2926534831adSStefano Zampini           if (temp_constraints > 1 || pcbddc->use_nnsp_true) {
2927534831adSStefano Zampini             useksp = PETSC_TRUE;
2928534831adSStefano Zampini           }
2929534831adSStefano Zampini           size_of_constraint = temp_indices[i+1]-temp_indices[i];
2930534831adSStefano Zampini           if (useksp) { /* experimental */
2931534831adSStefano Zampini             ierr = MatCreate(PETSC_COMM_SELF,&temp_mat);CHKERRQ(ierr);
2932534831adSStefano Zampini             ierr = MatSetType(temp_mat,impMatType);CHKERRQ(ierr);
2933534831adSStefano Zampini             ierr = MatSetSizes(temp_mat,size_of_constraint,size_of_constraint,size_of_constraint,size_of_constraint);CHKERRQ(ierr);
2934534831adSStefano Zampini             ierr = MatSeqAIJSetPreallocation(temp_mat,size_of_constraint,PETSC_NULL);CHKERRQ(ierr);
2935534831adSStefano Zampini           }
2936534831adSStefano Zampini           /* First _size_of_constraint-temp_constraints_ columns */
2937534831adSStefano Zampini           dual_dofs = size_of_constraint-temp_constraints;
2938534831adSStefano Zampini           start_constraint = i+1-temp_constraints;
2939534831adSStefano Zampini           for (s=0;s<dual_dofs;s++) {
2940534831adSStefano Zampini             is_indices[0] = s;
2941534831adSStefano Zampini             for (j=0;j<temp_constraints;j++) {
2942534831adSStefano Zampini               for (k=0;k<temp_constraints;k++) {
2943534831adSStefano Zampini                 temp_basis[j*temp_constraints+k]=temp_quadrature_constraint[temp_indices[start_constraint+k]+s+j+1];
2944534831adSStefano Zampini               }
2945534831adSStefano Zampini               work[j]=-temp_quadrature_constraint[temp_indices[start_constraint+j]+s];
2946534831adSStefano Zampini               is_indices[j+1]=s+j+1;
2947534831adSStefano Zampini             }
2948534831adSStefano Zampini             Bt = temp_constraints;
2949534831adSStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2950534831adSStefano Zampini             LAPACKgesv_(&Bt,&Bone,temp_basis,&Bt,ipiv,work,&Bt,&lierr);
2951534831adSStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESV Lapack routine %d",(int)lierr);
2952534831adSStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2953534831adSStefano Zampini             j = temp_indices_to_constraint_B[temp_indices[start_constraint]+s];
2954534831adSStefano Zampini             ierr = MatSetValues(pcbddc->ChangeOfBasisMatrix,temp_constraints,&temp_indices_to_constraint_B[temp_indices[start_constraint]+s+1],1,&j,work,INSERT_VALUES);CHKERRQ(ierr);
2955534831adSStefano Zampini             if (useksp) {
2956534831adSStefano Zampini               /* temp mat with transposed rows and columns */
2957534831adSStefano Zampini               ierr = MatSetValues(temp_mat,1,&s,temp_constraints,&is_indices[1],work,INSERT_VALUES);CHKERRQ(ierr);
2958534831adSStefano Zampini               ierr = MatSetValue(temp_mat,is_indices[0],is_indices[0],1.0,INSERT_VALUES);CHKERRQ(ierr);
2959534831adSStefano Zampini             }
2960534831adSStefano Zampini           }
2961534831adSStefano Zampini           if (useksp) {
2962534831adSStefano Zampini             /* last rows of temp_mat */
2963534831adSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2964534831adSStefano Zampini               is_indices[j] = j;
2965534831adSStefano Zampini             }
2966534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2967534831adSStefano Zampini               k = s + dual_dofs;
2968534831adSStefano Zampini               ierr = MatSetValues(temp_mat,1,&k,size_of_constraint,is_indices,&temp_quadrature_constraint[temp_indices[start_constraint+s]],INSERT_VALUES);CHKERRQ(ierr);
2969534831adSStefano Zampini             }
2970534831adSStefano Zampini             ierr = MatAssemblyBegin(temp_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2971534831adSStefano Zampini             ierr = MatAssemblyEnd(temp_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2972534831adSStefano Zampini             ierr = MatGetVecs(temp_mat,&temp_vec,PETSC_NULL);CHKERRQ(ierr);
2973534831adSStefano Zampini             ierr = KSPCreate(PETSC_COMM_SELF,&temp_ksp);CHKERRQ(ierr);
2974534831adSStefano Zampini             ierr = KSPSetOperators(temp_ksp,temp_mat,temp_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
2975534831adSStefano Zampini             ierr = KSPSetType(temp_ksp,KSPPREONLY);CHKERRQ(ierr);
2976ffe5efe1SStefano Zampini             ierr = KSPGetPC(temp_ksp,&temp_pc);CHKERRQ(ierr);
2977ffe5efe1SStefano Zampini             ierr = PCSetType(temp_pc,PCLU);CHKERRQ(ierr);
2978534831adSStefano Zampini             ierr = KSPSetUp(temp_ksp);CHKERRQ(ierr);
2979534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2980534831adSStefano Zampini               ierr = VecSet(temp_vec,0.0);CHKERRQ(ierr);
2981534831adSStefano Zampini               ierr = VecSetValue(temp_vec,s+dual_dofs,1.0,INSERT_VALUES);CHKERRQ(ierr);
2982534831adSStefano Zampini               ierr = VecAssemblyBegin(temp_vec);CHKERRQ(ierr);
2983534831adSStefano Zampini               ierr = VecAssemblyEnd(temp_vec);CHKERRQ(ierr);
2984534831adSStefano Zampini               ierr = KSPSolve(temp_ksp,temp_vec,temp_vec);CHKERRQ(ierr);
2985534831adSStefano Zampini               ierr = VecGetArray(temp_vec,&array_vector);CHKERRQ(ierr);
2986534831adSStefano Zampini               j = temp_indices_to_constraint_B[temp_indices[start_constraint+s]+size_of_constraint-s-1];
2987534831adSStefano Zampini               /* last columns of change of basis matrix associated to new primal dofs */
2988534831adSStefano Zampini               ierr = MatSetValues(pcbddc->ChangeOfBasisMatrix,size_of_constraint,&temp_indices_to_constraint_B[temp_indices[start_constraint+s]],1,&j,array_vector,INSERT_VALUES);CHKERRQ(ierr);
2989534831adSStefano Zampini               ierr = VecRestoreArray(temp_vec,&array_vector);CHKERRQ(ierr);
2990534831adSStefano Zampini             }
2991534831adSStefano Zampini             ierr = MatDestroy(&temp_mat);CHKERRQ(ierr);
2992534831adSStefano Zampini             ierr = KSPDestroy(&temp_ksp);CHKERRQ(ierr);
2993534831adSStefano Zampini             ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2994534831adSStefano Zampini           } else {
2995534831adSStefano Zampini             /* last columns of change of basis matrix associated to new primal dofs */
2996534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2997534831adSStefano Zampini               j = temp_indices_to_constraint_B[temp_indices[start_constraint+s]+size_of_constraint-s-1];
2998534831adSStefano Zampini               ierr = MatSetValues(pcbddc->ChangeOfBasisMatrix,size_of_constraint,&temp_indices_to_constraint_B[temp_indices[start_constraint+s]],1,&j,&temp_quadrature_constraint[temp_indices[start_constraint+s]],INSERT_VALUES);CHKERRQ(ierr);
2999534831adSStefano Zampini             }
3000534831adSStefano Zampini           }
3001534831adSStefano Zampini           /* prepare for the next cycle */
3002534831adSStefano Zampini           temp_constraints = 0;
300304eaf177SStefano Zampini           if (i != local_primal_size -1) {
3004534831adSStefano Zampini             temp_start_ptr = temp_indices_to_constraint_B[temp_indices[i+1]];
3005534831adSStefano Zampini           }
3006534831adSStefano Zampini         }
3007534831adSStefano Zampini       }
300804eaf177SStefano Zampini     }
3009534831adSStefano Zampini     /* assembling */
3010534831adSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3011534831adSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3012534831adSStefano Zampini     ierr = PetscFree(ipiv);CHKERRQ(ierr);
3013534831adSStefano Zampini     ierr = PetscFree(is_indices);CHKERRQ(ierr);
3014534831adSStefano Zampini   }
30153b03a366Sstefano_zampini   /* free workspace no longer needed */
30163b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
30173b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
30183b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
30193b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
30203b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
30213b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
3022534831adSStefano Zampini   ierr = PetscFree(change_basis);CHKERRQ(ierr);
30233b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
3024534831adSStefano Zampini   ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
3025534831adSStefano Zampini   ierr = PetscFree(local_to_B);CHKERRQ(ierr);
30263b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
30273425bc38SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
30283425bc38SStefano Zampini   ierr = PetscFree(iwork);CHKERRQ(ierr);
30293425bc38SStefano Zampini   ierr = PetscFree(ifail);CHKERRQ(ierr);
30303425bc38SStefano Zampini   ierr = PetscFree(singular_vectors);CHKERRQ(ierr);
30313425bc38SStefano Zampini #endif
3032da1bb401SStefano Zampini   for (k=0;k<nnsp_size;k++) {
3033da1bb401SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3034da1bb401SStefano Zampini   }
30353b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
30363b03a366Sstefano_zampini   PetscFunctionReturn(0);
30373b03a366Sstefano_zampini }
30383b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
30390c7d97c5SJed Brown #undef __FUNCT__
30400c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
304153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
30420c7d97c5SJed Brown {
30430c7d97c5SJed Brown   PetscErrorCode    ierr;
30440c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
30450c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
30460c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
3047534831adSStefano Zampini   Mat               change_mat_all;
30480c7d97c5SJed Brown   IS                is_R_local;
30490c7d97c5SJed Brown   IS                is_V_local;
30500c7d97c5SJed Brown   IS                is_C_local;
30510c7d97c5SJed Brown   IS                is_aux1;
30520c7d97c5SJed Brown   IS                is_aux2;
305319fd82e9SBarry Smith   VecType           impVecType;
305419fd82e9SBarry Smith   MatType           impMatType;
30550c7d97c5SJed Brown   PetscInt          n_R=0;
30560c7d97c5SJed Brown   PetscInt          n_D=0;
30570c7d97c5SJed Brown   PetscInt          n_B=0;
30580c7d97c5SJed Brown   PetscScalar       zero=0.0;
30590c7d97c5SJed Brown   PetscScalar       one=1.0;
30600c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
30610c7d97c5SJed Brown   PetscScalar*      array;
30620c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
30630c7d97c5SJed Brown   PetscInt          *idx_R_local;
30640c7d97c5SJed Brown   PetscInt          *idx_V_B;
30650c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
30660c7d97c5SJed Brown   PetscScalar       *constraints_errors;
30670c7d97c5SJed Brown   /* auxiliary indices */
3068534831adSStefano Zampini   PetscInt          i,j,k;
3069e269702eSStefano Zampini   /* for verbose output of bddc */
3070e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
3071e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
3072a0ba757dSStefano Zampini   /* for counting coarse dofs */
3073534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
30743b03a366Sstefano_zampini   PetscInt          size_of_constraint;
30753b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
30763b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
3077534831adSStefano Zampini   PetscInt          *vertices,*nnz,*is_indices,*temp_indices;
30780c7d97c5SJed Brown 
30790c7d97c5SJed Brown   PetscFunctionBegin;
30800c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
30810c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
3082534831adSStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
3083534831adSStefano Zampini   impMatType = MATSEQDENSE;
3084534831adSStefano Zampini   impVecType = VECSEQ;
3085da1bb401SStefano Zampini   /* get vertex indices from constraint matrix */
3086534831adSStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
3087534831adSStefano Zampini   n_vertices=0;
3088da1bb401SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
3089da1bb401SStefano Zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3090da1bb401SStefano Zampini     if (size_of_constraint == 1) {
3091534831adSStefano Zampini       vertices[n_vertices]=row_cmat_indices[0];
3092534831adSStefano Zampini       n_vertices++;
3093a0ba757dSStefano Zampini     }
3094da1bb401SStefano Zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3095a0ba757dSStefano Zampini   }
3096534831adSStefano Zampini   /* Set number of constraints */
3097534831adSStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
3098534831adSStefano Zampini 
3099534831adSStefano Zampini   /* vertices in boundary numbering */
3100534831adSStefano Zampini   if (n_vertices) {
3101534831adSStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
3102534831adSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3103534831adSStefano Zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
3104534831adSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3105534831adSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3106534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3107534831adSStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
3108534831adSStefano Zampini     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3109534831adSStefano Zampini     for (i=0; i<n_vertices; i++) {
3110534831adSStefano Zampini       j=0;
3111534831adSStefano Zampini       while (array[j] != i) {j++;}
3112534831adSStefano Zampini       idx_V_B[i]=j;
3113534831adSStefano Zampini     }
3114534831adSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3115534831adSStefano Zampini   }
3116534831adSStefano Zampini 
3117534831adSStefano Zampini   /* transform local matrices if needed */
3118534831adSStefano Zampini   if (pcbddc->usechangeofbasis) {
3119534831adSStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
3120534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3121534831adSStefano Zampini     for (i=0;i<n_D;i++) {
3122534831adSStefano Zampini       nnz[is_indices[i]]=1;
3123534831adSStefano Zampini     }
3124534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3125534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3126534831adSStefano Zampini     k=1;
3127534831adSStefano Zampini     for (i=0;i<n_B;i++) {
3128534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
3129534831adSStefano Zampini       nnz[is_indices[i]]=j;
3130534831adSStefano Zampini       if (k < j) {
3131534831adSStefano Zampini         k = j;
3132534831adSStefano Zampini       }
3133534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
3134534831adSStefano Zampini     }
3135534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3136534831adSStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
3137534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
3138534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
3139534831adSStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3140534831adSStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
3141534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
3142534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3143534831adSStefano Zampini     for (i=0;i<n_D;i++) {
3144534831adSStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3145534831adSStefano Zampini     }
3146534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3147534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3148534831adSStefano Zampini     for (i=0;i<n_B;i++) {
3149534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
3150534831adSStefano Zampini       for (k=0;k<j;k++) {
3151534831adSStefano Zampini         temp_indices[k]=is_indices[row_cmat_indices[k]];
3152534831adSStefano Zampini       }
3153534831adSStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
3154534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
3155534831adSStefano Zampini     }
3156534831adSStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3157534831adSStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3158534831adSStefano Zampini     ierr = MatPtAP(matis->A,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
3159534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
3160534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
3161534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
3162534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
3163534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
3164534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
3165534831adSStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
3166534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3167534831adSStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
3168534831adSStefano Zampini   } else {
3169534831adSStefano Zampini     /* without change of basis, the local matrix is unchanged */
3170534831adSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
3171534831adSStefano Zampini     pcbddc->local_mat = matis->A;
3172534831adSStefano Zampini   }
31730bdf917eSStefano Zampini   /* Change global null space passed in by the user if change of basis has been performed */
31740bdf917eSStefano Zampini   if (pcbddc->NullSpace && pcbddc->usechangeofbasis) {
31750bdf917eSStefano Zampini     ierr = PCBDDCAdaptNullSpace(pc);CHKERRQ(ierr);
31760bdf917eSStefano Zampini   }
3177a0ba757dSStefano Zampini 
31780c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
31790c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
31800c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
31813b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
31823b03a366Sstefano_zampini   ierr = PetscMalloc((pcis->n - n_vertices)*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
31830c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
31840c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3185e269702eSStefano Zampini   if (dbg_flag) {
31860c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
31870c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31880c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
31890c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
31903b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr);
3191534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
31920c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31930c7d97c5SJed Brown   }
3194534831adSStefano Zampini 
31950c7d97c5SJed Brown   /* Allocate needed vectors */
3196534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
31973972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
31980c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
31990c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
32000c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
32010c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
3202d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
32030c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
32040c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
32050c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
32060c7d97c5SJed Brown 
32070c7d97c5SJed Brown   /* Creating some index sets needed  */
32080c7d97c5SJed Brown   /* For submatrices */
3209da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
32103b03a366Sstefano_zampini   if (n_vertices)    {
3211da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_OWN_POINTER,&is_V_local);CHKERRQ(ierr);
32123b03a366Sstefano_zampini   }
3213da1bb401SStefano Zampini   if (n_constraints) {
3214da1bb401SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
3215da1bb401SStefano Zampini   }
3216da1bb401SStefano Zampini 
32170c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
32180c7d97c5SJed Brown   {
32190c7d97c5SJed Brown     PetscInt   *aux_array1;
32200c7d97c5SJed Brown     PetscInt   *aux_array2;
32212e8d2280SStefano Zampini     PetscInt   *idx_I_local;
32220c7d97c5SJed Brown 
32233b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
32243b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
32250c7d97c5SJed Brown 
32262e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
32270c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
32282e8d2280SStefano Zampini     for (i=0; i<n_D; i++) { array[idx_I_local[i]] = 0; }
32292e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
32302e8d2280SStefano Zampini     for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[j] = i; j++; } }
32310c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3232da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
32332e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32342e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32350c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
32362e8d2280SStefano Zampini     for (i=0, j=0; i<n_B; i++) { if (array[i] == one) { aux_array2[j] = i; j++; } }
32373828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3238da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
32390c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
32400c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
32410c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
32420c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
32430c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
32440c7d97c5SJed Brown 
324529622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
32460c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
32470c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
32482e8d2280SStefano Zampini       for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == zero) { aux_array1[j] = i; j++; } }
32490c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3250da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
32510c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
32520c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
32530c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
32540c7d97c5SJed Brown     }
32550c7d97c5SJed Brown   }
32560c7d97c5SJed Brown 
32570c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
32580c7d97c5SJed Brown   {
32590c7d97c5SJed Brown     Mat  A_RR;
326053cdbc3dSStefano Zampini     PC   pc_temp;
32610c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
326253cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
326353cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
326453cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
326553cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3266da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
32670c7d97c5SJed Brown     /* default */
326853cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
326953cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32700c7d97c5SJed Brown     /* Allow user's customization */
327153cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3272950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
3273950d796eSStefano Zampini     if (!n_D) {
32742e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3275950d796eSStefano Zampini     }
327653cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
327753cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
32783972b0daSStefano Zampini     /* set ksp_D into pcis data */
32793972b0daSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
32803972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
32813972b0daSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
32820c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
3283534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
328453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
328553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
328653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
328753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3288da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
32890c7d97c5SJed Brown     /* default */
329053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
329153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32920c7d97c5SJed Brown     /* Allow user's customization */
329353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3294950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
3295950d796eSStefano Zampini     if (!pcis->n) {
32962e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3297950d796eSStefano Zampini     }
329853cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
329953cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
330029622bf0SStefano Zampini     /* check Dirichlet and Neumann solvers and adapt them is a nullspace correction is needed */
3301b76ba322SStefano Zampini     {
33020c7d97c5SJed Brown       Vec         temp_vec;
3303b76ba322SStefano Zampini       PetscReal   value;
3304b76ba322SStefano Zampini       PetscMPIInt use_exact,use_exact_reduced;
33050c7d97c5SJed Brown 
3306a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
3307a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
3308a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3309a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
3310a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
3311a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
331229622bf0SStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
3313b76ba322SStefano Zampini       use_exact = 1;
3314b76ba322SStefano Zampini       if (PetscAbsReal(value) > 1.e-4) {
3315b76ba322SStefano Zampini         use_exact = 0;
3316b76ba322SStefano Zampini       }
3317b76ba322SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,((PetscObject)pc)->comm);CHKERRQ(ierr);
3318b76ba322SStefano Zampini       pcbddc->use_exact_dirichlet = (PetscBool) use_exact_reduced;
3319b76ba322SStefano Zampini       if (dbg_flag) {
3320a0ba757dSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3321a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3322a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
3323a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
332429622bf0SStefano Zampini       }
332529622bf0SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->inexact_prec_type) {
332629622bf0SStefano Zampini         ierr = PCBDDCAdaptLocalProblem(pc,pcis->is_I_local);
332729622bf0SStefano Zampini       }
3328d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
3329d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
3330d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3331d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
3332d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
3333d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
3334e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
333529622bf0SStefano Zampini       use_exact = 1;
333629622bf0SStefano Zampini       if (PetscAbsReal(value) > 1.e-4) {
333729622bf0SStefano Zampini         use_exact = 0;
333829622bf0SStefano Zampini       }
333929622bf0SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,((PetscObject)pc)->comm);CHKERRQ(ierr);
334029622bf0SStefano Zampini       if (dbg_flag) {
33410c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
3342d49ef151SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
33430c7d97c5SJed Brown       }
334429622bf0SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) {
334529622bf0SStefano Zampini         ierr = PCBDDCAdaptLocalProblem(pc,is_R_local);
334629622bf0SStefano Zampini       }
3347b76ba322SStefano Zampini     }
33480c7d97c5SJed Brown     /* free Neumann problem's matrix */
33490c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
33500c7d97c5SJed Brown   }
33510c7d97c5SJed Brown 
33520c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
33530c7d97c5SJed Brown   {
33540c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
33550bdf917eSStefano Zampini     Mat          M1;
33560c7d97c5SJed Brown     Mat          C_CR;
33573b03a366Sstefano_zampini     Mat          AUXMAT;
33580c7d97c5SJed Brown     Vec          vec1_C;
33590c7d97c5SJed Brown     Vec          vec2_C;
33600c7d97c5SJed Brown     Vec          vec1_V;
33610c7d97c5SJed Brown     Vec          vec2_V;
33620c7d97c5SJed Brown     PetscInt     *nnz;
33630c7d97c5SJed Brown     PetscInt     *auxindices;
336453cdbc3dSStefano Zampini     PetscInt     index;
33650c7d97c5SJed Brown     PetscScalar* array2;
33660c7d97c5SJed Brown     MatFactorInfo matinfo;
33670c7d97c5SJed Brown 
33680c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
33690c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
33700c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
33710c7d97c5SJed Brown     for (i=0;i<pcis->n;i++) {auxindices[i]=i;}
33720c7d97c5SJed Brown 
33730c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
33743b03a366Sstefano_zampini     if (n_vertices) {
33750c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
33763b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
33770c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
33780c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
33790c7d97c5SJed Brown     }
3380534831adSStefano Zampini     if (n_constraints) {
33810c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
3382534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
33830c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
33840c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
33850c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
33860c7d97c5SJed Brown     }
33870c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
33883b03a366Sstefano_zampini     if (n_constraints) {
33890c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
33903b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
33910c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
33923b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
33930c7d97c5SJed Brown 
339457a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
339557a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
339657a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
339757a90decSStefano Zampini 
33980c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
33993b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
34003b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
34013b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
340257a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
340357a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
34043b03a366Sstefano_zampini         for (j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
340557a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
340657a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
34073b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
340853cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
34093b03a366Sstefano_zampini         /* Set values */
34100c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
34113b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
34120c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
34130c7d97c5SJed Brown       }
34140c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34150c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34160c7d97c5SJed Brown 
34170c7d97c5SJed Brown       /* Assemble AUXMAT = (LUFactor)(-C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */
34180c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
3419d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
34203b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
34210c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
34220c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
34230c7d97c5SJed Brown 
34243b03a366Sstefano_zampini       /* Assemble explicitly M1 = (C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} needed in preproc  */
3425d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
34263b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
34270c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
34283b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
34293b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
34300c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
34310c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
34320c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
34330c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
34340c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
34350c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
34360c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
34373b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
34380c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
34390c7d97c5SJed Brown       }
34400c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34410c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34420c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
34430c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
34440c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
34450c7d97c5SJed Brown 
34460c7d97c5SJed Brown     }
34470c7d97c5SJed Brown 
34480c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
34493b03a366Sstefano_zampini     if (n_vertices) {
3450534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3451534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3452534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
34530c7d97c5SJed Brown     }
34540c7d97c5SJed Brown 
34550c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
3456d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
34570c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
34580c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
34593b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
346029622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
3461d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
34620c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
34630c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
34643b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
34650c7d97c5SJed Brown     }
34660c7d97c5SJed Brown 
3467e269702eSStefano Zampini     if (dbg_flag) {
34680c7d97c5SJed Brown       ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
34690c7d97c5SJed Brown       ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
34700c7d97c5SJed Brown     }
34713b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
34720c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
34730c7d97c5SJed Brown 
34740c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
34753b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++) {
34760c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
34770c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
34780c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
34790c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
34800c7d97c5SJed Brown       /* solution of saddle point problem */
34810bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
34820bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
34830c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
34843b03a366Sstefano_zampini       if (n_constraints) {
34850c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
34860c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
34870c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
34880c7d97c5SJed Brown       }
34890c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
34900c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
34910c7d97c5SJed Brown 
34920c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
34930c7d97c5SJed Brown       /* coarse basis functions */
34940c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
34950c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
34960c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
34970c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
34983b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
34990c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
35000c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
350129622bf0SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag) {
35020c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35030c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35040c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35053b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
35060c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35070c7d97c5SJed Brown       }
35080c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
35090c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
3510da1bb401SStefano Zampini       for (j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } /* WARNING -> column major ordering */
35110c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35123b03a366Sstefano_zampini       if (n_constraints) {
35130c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
3514da1bb401SStefano Zampini         for (j=0;j<n_constraints;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j+n_vertices] = array[j]; } /* WARNING -> column major ordering */
35150c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35160c7d97c5SJed Brown       }
35170c7d97c5SJed Brown 
3518e269702eSStefano Zampini       if (dbg_flag) {
35190c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
3520d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
35210c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35220c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35230c7d97c5SJed Brown         for (j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
35243b03a366Sstefano_zampini         array[ vertices[i] ] = one;
35250c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35260c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35270c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
3528d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
35290c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
35300c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
35313b03a366Sstefano_zampini         for (j=0;j<n_vertices;j++) { array2[j]=array[j]; }
35320c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35333b03a366Sstefano_zampini         if (n_constraints) {
35340c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
35353b03a366Sstefano_zampini           for (j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
35360c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35370c7d97c5SJed Brown         }
35380c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
35390c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
35400c7d97c5SJed Brown         /* check saddle point solution */
3541534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
35423b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
35433b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
35443b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
35450c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35463b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
35470c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35483b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
35490c7d97c5SJed Brown       }
35500c7d97c5SJed Brown     }
35510c7d97c5SJed Brown 
35523b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++) {
3553d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
35540c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
35550c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
35560c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
35570c7d97c5SJed Brown       /* solution of saddle point problem */
35580c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
35590c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
35600c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
35613b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
35620c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
35630c7d97c5SJed Brown       /* coarse basis functions */
35643b03a366Sstefano_zampini       index=i+n_vertices;
35650c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
35660c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35670c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35680c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
356953cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
35700c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
357129622bf0SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag) {
35720c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35730c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35740c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
357553cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
35760c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35770c7d97c5SJed Brown       }
35780c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
35793b03a366Sstefano_zampini       if (n_vertices) {
35800c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
3581da1bb401SStefano Zampini         for (j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} /* WARNING -> column major ordering */
35820c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35830c7d97c5SJed Brown       }
35840c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
3585da1bb401SStefano Zampini       for (j=0;j<n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+n_vertices]=array[j];} /* WARNING -> column major ordering */
35860c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35870c7d97c5SJed Brown 
3588e269702eSStefano Zampini       if (dbg_flag) {
35890c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
359053cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
35910c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35920c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35930c7d97c5SJed Brown         for (j=0;j<n_R;j++) { array[ idx_R_local[j] ] = array2[j]; }
35940c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35950c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35960c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
359753cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
35980c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
35993b03a366Sstefano_zampini         if (n_vertices) {
36000c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
36013b03a366Sstefano_zampini           for (j=0;j<n_vertices;j++) {array2[j]=-array[j];}
36020c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
36030c7d97c5SJed Brown         }
36040c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
36053b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
36060c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
36070c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
36083972b0daSStefano Zampini         /* check saddle point solution */
3609534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
36103b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
361153cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
36123b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
36130c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
361453cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
36150c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
361653cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
36170c7d97c5SJed Brown       }
36180c7d97c5SJed Brown     }
36190c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36200c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
362129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
36220c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36230c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36240c7d97c5SJed Brown     }
36250c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
36260c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
36279d2fce94SStefano Zampini     if (dbg_flag) {
36280c7d97c5SJed Brown       Mat         coarse_sub_mat;
36290c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
36300c7d97c5SJed Brown       Mat         coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
363119fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
36320c7d97c5SJed Brown       PetscScalar value;
36330c7d97c5SJed Brown 
3634c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3635c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3636c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3637c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3638c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
3639c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3640c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
3641c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
36420c7d97c5SJed Brown 
36430c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36440c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
36450c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
364653cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
364753cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
364853cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
3649c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
365053cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
365153cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
3652c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
365353cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
365453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365853cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
36590c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
36600c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
36610c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
36620c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
366353cdbc3dSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr); }
36640c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
366553cdbc3dSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr); }
36660c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
366753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
366853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
366953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
367053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
367153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
367253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
367353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
367453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
367553cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
367653cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
367753cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
36780c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
36790c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
36800c7d97c5SJed Brown     }
36810c7d97c5SJed Brown     /* free memory */
36823b03a366Sstefano_zampini     if (n_vertices) {
36830c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
36840c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
36850c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
36860c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
36870c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
36880c7d97c5SJed Brown     }
3689534831adSStefano Zampini     if (n_constraints) {
36900c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
36910c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
36920c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
36930c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
36940c7d97c5SJed Brown     }
3695a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
3696a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3697a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
3698a929c220SStefano Zampini     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
3699a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
37000c7d97c5SJed Brown   }
37010c7d97c5SJed Brown   /* free memory */
37023b03a366Sstefano_zampini   if (n_vertices) {
37030c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
37040c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
37050c7d97c5SJed Brown   }
37060c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
37070c7d97c5SJed Brown 
37080c7d97c5SJed Brown   PetscFunctionReturn(0);
37090c7d97c5SJed Brown }
37100c7d97c5SJed Brown 
37110c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
37120c7d97c5SJed Brown 
37130c7d97c5SJed Brown #undef __FUNCT__
37140c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
371553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
37160c7d97c5SJed Brown {
37170c7d97c5SJed Brown   Mat_IS                 *matis    = (Mat_IS*)pc->pmat->data;
37180c7d97c5SJed Brown   PC_BDDC                *pcbddc   = (PC_BDDC*)pc->data;
37190c7d97c5SJed Brown   PC_IS                  *pcis     = (PC_IS*)pc->data;
37200c7d97c5SJed Brown   MPI_Comm               prec_comm = ((PetscObject)pc)->comm;
37210c7d97c5SJed Brown   MPI_Comm               coarse_comm;
37220c7d97c5SJed Brown 
37230c7d97c5SJed Brown   /* common to all choiches */
37240c7d97c5SJed Brown   PetscScalar            *temp_coarse_mat_vals;
37250c7d97c5SJed Brown   PetscScalar            *ins_coarse_mat_vals;
37260c7d97c5SJed Brown   PetscInt               *ins_local_primal_indices;
37270c7d97c5SJed Brown   PetscMPIInt            *localsizes2,*localdispl2;
37280c7d97c5SJed Brown   PetscMPIInt            size_prec_comm;
37290c7d97c5SJed Brown   PetscMPIInt            rank_prec_comm;
37300c7d97c5SJed Brown   PetscMPIInt            active_rank=MPI_PROC_NULL;
37310c7d97c5SJed Brown   PetscMPIInt            master_proc=0;
37320c7d97c5SJed Brown   PetscInt               ins_local_primal_size;
37330c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
37340c7d97c5SJed Brown   PetscMPIInt            *ranks_recv;
37350c7d97c5SJed Brown   PetscMPIInt            count_recv=0;
37360c7d97c5SJed Brown   PetscMPIInt            rank_coarse_proc_send_to;
37370c7d97c5SJed Brown   PetscMPIInt            coarse_color = MPI_UNDEFINED;
37380c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
37390c7d97c5SJed Brown   /* some other variables */
37400c7d97c5SJed Brown   PetscErrorCode         ierr;
374119fd82e9SBarry Smith   MatType                coarse_mat_type;
374219fd82e9SBarry Smith   PCType                 coarse_pc_type;
374319fd82e9SBarry Smith   KSPType                coarse_ksp_type;
374453cdbc3dSStefano Zampini   PC                     pc_temp;
37454fad6a16SStefano Zampini   PetscInt               i,j,k;
37463b03a366Sstefano_zampini   PetscInt               max_it_coarse_ksp=1;  /* don't increase this value */
3747e269702eSStefano Zampini   /* verbose output viewer */
3748e269702eSStefano Zampini   PetscViewer            viewer=pcbddc->dbg_viewer;
3749e269702eSStefano Zampini   PetscBool              dbg_flag=pcbddc->dbg_flag;
3750142dfd88SStefano Zampini 
3751ea7e1babSStefano Zampini   PetscInt               offset,offset2;
3752a929c220SStefano Zampini   PetscMPIInt            im_active,active_procs;
3753523858cfSStefano Zampini   PetscInt               *dnz,*onz;
3754142dfd88SStefano Zampini 
3755142dfd88SStefano Zampini   PetscBool              setsym,issym=PETSC_FALSE;
37560c7d97c5SJed Brown 
37570c7d97c5SJed Brown   PetscFunctionBegin;
37580c7d97c5SJed Brown   ins_local_primal_indices = 0;
37590c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
37600c7d97c5SJed Brown   localsizes2              = 0;
37610c7d97c5SJed Brown   localdispl2              = 0;
37620c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
37630c7d97c5SJed Brown   coarse_ISLG              = 0;
37640c7d97c5SJed Brown 
376553cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
376653cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
3767142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
3768142dfd88SStefano Zampini 
3769beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
3770beed3852SStefano Zampini   {
3771ef028eecSStefano Zampini     PetscInt     *auxlocal_primal;
3772da1bb401SStefano Zampini     PetscInt     *row_cmat_indices;
37732e8d2280SStefano Zampini     PetscInt     *aux_ordering;
37742e8d2280SStefano Zampini     PetscInt     *row_cmat_global_indices;
3775ef028eecSStefano Zampini     PetscInt     *dof_sizes,*dof_displs;
37763b03a366Sstefano_zampini     PetscInt     size_of_constraint;
37772e8d2280SStefano Zampini     PetscBool    *array_bool;
3778ef028eecSStefano Zampini     PetscBool    first_found;
3779ef028eecSStefano Zampini     PetscInt     first_index,old_index,s;
3780ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
3781ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
3782ef028eecSStefano Zampini 
3783ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
3784beed3852SStefano Zampini 
3785beed3852SStefano Zampini     /* Construct needed data structures for message passing */
3786ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
3787ffe5efe1SStefano Zampini     j = 0;
3788142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3789ffe5efe1SStefano Zampini       j = size_prec_comm;
3790ffe5efe1SStefano Zampini     }
3791ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
3792ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
3793beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
3794142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
37955619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
3796ffe5efe1SStefano Zampini     } else {
3797ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3798ffe5efe1SStefano Zampini     }
3799beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
3800ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
3801beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
3802beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
3803beed3852SStefano Zampini     }
3804beed3852SStefano Zampini 
3805da1bb401SStefano Zampini     /* First let's count coarse dofs.
3806beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
3807beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
3808beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
3809ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
38102e8d2280SStefano Zampini     j = 0;
38112e8d2280SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
38122e8d2280SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
38132e8d2280SStefano Zampini       if (j < size_of_constraint) {
38142e8d2280SStefano Zampini         j = size_of_constraint;
38152e8d2280SStefano Zampini       }
38162e8d2280SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
38172e8d2280SStefano Zampini     }
38182e8d2280SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&aux_ordering);CHKERRQ(ierr);
38192e8d2280SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&row_cmat_global_indices);CHKERRQ(ierr);
38202e8d2280SStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscBool),&array_bool);CHKERRQ(ierr);
38212e8d2280SStefano Zampini     for (i=0;i<pcis->n;i++) {
38222e8d2280SStefano Zampini       array_bool[i] = PETSC_FALSE;
38232e8d2280SStefano Zampini     }
3824da1bb401SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3825da1bb401SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
38263b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
38272e8d2280SStefano Zampini         aux_ordering[j] = j;
38282e8d2280SStefano Zampini       }
38292e8d2280SStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
38302e8d2280SStefano Zampini       ierr = PetscSortIntWithPermutation(size_of_constraint,row_cmat_global_indices,aux_ordering);CHKERRQ(ierr);
38312e8d2280SStefano Zampini       for (j=0; j<size_of_constraint; j++) {
38322e8d2280SStefano Zampini         k = row_cmat_indices[aux_ordering[j]];
38332e8d2280SStefano Zampini         if (!array_bool[k]) {
38342e8d2280SStefano Zampini           array_bool[k] = PETSC_TRUE;
3835da1bb401SStefano Zampini           auxlocal_primal[i] = k;
3836beed3852SStefano Zampini           break;
3837beed3852SStefano Zampini         }
3838beed3852SStefano Zampini       }
3839da1bb401SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3840beed3852SStefano Zampini     }
38412e8d2280SStefano Zampini     ierr = PetscFree(aux_ordering);CHKERRQ(ierr);
3842ef028eecSStefano Zampini     ierr = PetscFree(array_bool);CHKERRQ(ierr);
3843ef028eecSStefano Zampini     ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
38442e8d2280SStefano Zampini 
3845ef028eecSStefano Zampini     /* Compute number of coarse dofs */
3846ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
3847ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3848ef028eecSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3849ef028eecSStefano Zampini       array[auxlocal_primal[i]]=1.0;
3850ef028eecSStefano Zampini     }
3851ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3852ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3853ef028eecSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3854ef028eecSStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3855ef028eecSStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
3856ef028eecSStefano Zampini     pcbddc->coarse_size = (PetscInt)coarsesum;
3857ef028eecSStefano Zampini 
3858ef028eecSStefano Zampini     /* Fill pcis->vec1_global with cumulative function for global numbering */
3859ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_global,&array);CHKERRQ(ierr);
3860ef028eecSStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&s);CHKERRQ(ierr);
3861ef028eecSStefano Zampini     k = 0;
3862ef028eecSStefano Zampini     first_index = -1;
3863ef028eecSStefano Zampini     first_found = PETSC_FALSE;
3864ef028eecSStefano Zampini     for (i=0;i<s;i++) {
3865ef028eecSStefano Zampini       if (!first_found && array[i] > 0.0) {
3866ef028eecSStefano Zampini         first_found = PETSC_TRUE;
3867ef028eecSStefano Zampini         first_index = i;
3868ef028eecSStefano Zampini       }
3869ef028eecSStefano Zampini       k += (PetscInt)array[i];
3870ef028eecSStefano Zampini     }
3871ef028eecSStefano Zampini     j = (!rank_prec_comm ? size_prec_comm : 0);
3872ef028eecSStefano Zampini     ierr = PetscMalloc(j*sizeof(*dof_sizes),&dof_sizes);CHKERRQ(ierr);
3873ef028eecSStefano Zampini     ierr = PetscMalloc(j*sizeof(*dof_displs),&dof_displs);CHKERRQ(ierr);
3874ef028eecSStefano Zampini     ierr = MPI_Gather(&k,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3875ef028eecSStefano Zampini     if (!rank_prec_comm) {
3876ef028eecSStefano Zampini       dof_displs[0]=0;
3877ef028eecSStefano Zampini       for (i=1;i<size_prec_comm;i++) {
3878ef028eecSStefano Zampini         dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
3879ef028eecSStefano Zampini       }
3880ef028eecSStefano Zampini     }
3881ef028eecSStefano Zampini     ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&k,1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3882ef028eecSStefano Zampini     if (first_found) {
3883ef028eecSStefano Zampini       array[first_index] += k;
3884ef028eecSStefano Zampini       old_index = first_index;
3885ef028eecSStefano Zampini       for (i=first_index+1;i<s;i++) {
3886ef028eecSStefano Zampini         if (array[i] > 0.0) {
3887ef028eecSStefano Zampini           array[i] += array[old_index];
3888ef028eecSStefano Zampini           old_index = i;
3889ef028eecSStefano Zampini         }
3890ef028eecSStefano Zampini       }
3891ef028eecSStefano Zampini     }
3892ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_global,&array);CHKERRQ(ierr);
3893ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
3894ef028eecSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3895ef028eecSStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3896ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3897ef028eecSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3898ef028eecSStefano Zampini       pcbddc->local_primal_indices[i] = (PetscInt)array[auxlocal_primal[i]]-1;
3899ef028eecSStefano Zampini     }
3900ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3901ef028eecSStefano Zampini     ierr = PetscFree(dof_displs);CHKERRQ(ierr);
3902ef028eecSStefano Zampini     ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
3903ef028eecSStefano Zampini 
3904ef028eecSStefano Zampini     if (dbg_flag) {
39052e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39062e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
39072e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
39082e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
39092e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3910ef028eecSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
3911ef028eecSStefano Zampini         array[auxlocal_primal[i]]=1.0;
39122e8d2280SStefano Zampini       }
3913beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39142e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3915da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3916da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3917da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3918da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3919da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39202e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
39212e8d2280SStefano Zampini         if (array[i] == 1.0) {
39222e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
39232e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
39242e8d2280SStefano Zampini         }
39252e8d2280SStefano Zampini       }
39262e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39272e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
39282e8d2280SStefano Zampini         if (array[i] > 0.0) {
39292e8d2280SStefano Zampini           array[i] = 1.0/array[i];
39302e8d2280SStefano Zampini         }
39312e8d2280SStefano Zampini       }
3932da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39332e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3934da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3935da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3936da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
39372e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
39382e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39392e8d2280SStefano Zampini     }
3940142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
39410bdf917eSStefano Zampini   }
39420bdf917eSStefano Zampini 
39432e8d2280SStefano Zampini   if (dbg_flag) {
39447cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
39452e8d2280SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39462e8d2280SStefano Zampini   }
39472e8d2280SStefano Zampini 
3948a929c220SStefano Zampini   im_active = 0;
39490bdf917eSStefano Zampini   if (pcis->n) { im_active = 1; }
3950a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
39510bdf917eSStefano Zampini 
39520bdf917eSStefano Zampini   /* adapt coarse problem type */
39534fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
39544fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
3955a929c220SStefano Zampini       if ((active_procs/pcbddc->coarsening_ratio) < 2) {
39560bdf917eSStefano Zampini         if (dbg_flag) {
3957a929c220SStefano 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);
39580bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39590bdf917eSStefano Zampini         }
39600bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
3961142dfd88SStefano Zampini       }
39624fad6a16SStefano Zampini     } else {
39634fad6a16SStefano Zampini       if (dbg_flag) {
3964a929c220SStefano 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);
39654fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39664fad6a16SStefano Zampini       }
39674fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
39684fad6a16SStefano Zampini     }
39694fad6a16SStefano Zampini   }
3970beed3852SStefano Zampini 
39710c7d97c5SJed Brown   switch (pcbddc->coarse_problem_type) {
39720c7d97c5SJed Brown 
3973da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
39740c7d97c5SJed Brown     {
39750c7d97c5SJed Brown       /* we need additional variables */
39760c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
39770c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
39780c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
39790c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
39800c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
39810c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
39820c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
39830c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
39840c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
39850c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
39860c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
39870c7d97c5SJed Brown       MetisInt    *faces_adjncy;
39880c7d97c5SJed Brown       MetisInt    *faces_xadj;
39890c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
39900c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
39910c7d97c5SJed Brown       PetscInt    *array_int;
39920c7d97c5SJed Brown       PetscMPIInt my_faces=0;
39930c7d97c5SJed Brown       PetscMPIInt total_faces=0;
39943828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
39950c7d97c5SJed Brown 
39960c7d97c5SJed Brown       /* define some quantities */
39970c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
39980c7d97c5SJed Brown       coarse_mat_type = MATIS;
39990c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
4000142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
40010c7d97c5SJed Brown 
40020c7d97c5SJed Brown       /* details of coarse decomposition */
4003a929c220SStefano Zampini       n_subdomains = active_procs;
40040c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
4005a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
40063828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
40073828260eSStefano Zampini 
4008a929c220SStefano Zampini #if 0
4009a929c220SStefano Zampini       PetscMPIInt     *old_ranks;
4010a929c220SStefano Zampini       PetscInt        *new_ranks,*jj,*ii;
4011a929c220SStefano Zampini       MatPartitioning mat_part;
4012a929c220SStefano Zampini       IS              coarse_new_decomposition,is_numbering;
4013a929c220SStefano Zampini       PetscViewer     viewer_test;
4014a929c220SStefano Zampini       MPI_Comm        test_coarse_comm;
4015a929c220SStefano Zampini       PetscMPIInt     test_coarse_color;
4016a929c220SStefano Zampini       Mat             mat_adj;
4017a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
4018a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
4019a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
4020a929c220SStefano Zampini       test_coarse_color = (im_active ? 0 : MPI_UNDEFINED);
4021a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
4022a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
4023a929c220SStefano Zampini       if (im_active) {
4024a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
4025a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
4026a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
4027a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
4028a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
4029a929c220SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
4030a929c220SStefano Zampini           new_ranks[i] = -1;
4031a929c220SStefano Zampini         }
4032a929c220SStefano Zampini         for (i=0;i<n_subdomains;i++) {
4033a929c220SStefano Zampini           new_ranks[old_ranks[i]] = i;
4034a929c220SStefano Zampini         }
4035a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
4036a929c220SStefano Zampini         k = pcis->n_neigh-1;
4037a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
4038a929c220SStefano Zampini         ii[0]=0;
4039a929c220SStefano Zampini         ii[1]=k;
4040a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
4041a929c220SStefano Zampini         for (i=0;i<k;i++) {
4042a929c220SStefano Zampini           jj[i]=new_ranks[pcis->neigh[i+1]];
4043a929c220SStefano Zampini         }
4044a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
4045a929c220SStefano Zampini         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,PETSC_NULL,&mat_adj);CHKERRQ(ierr);
4046a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
4047a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
4048a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
4049a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
4050a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
4051a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
4052a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
4053a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
4054a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
4055a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
4056a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
4057a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
4058a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
4059a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
4060a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
4061a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
4062a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
4063a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
4064a929c220SStefano Zampini       }
4065a929c220SStefano Zampini #endif
4066a929c220SStefano Zampini 
40674fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
40680c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
40693828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
40700c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {/* i=1 so I don't count myself -> faces nodes counts to 1 */
40710c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40720c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
40730c7d97c5SJed Brown         }
40740c7d97c5SJed Brown       }
40750c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {
40760c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40777cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0) {
40780c7d97c5SJed Brown             my_faces++;
40790c7d97c5SJed Brown             break;
40800c7d97c5SJed Brown           }
40810c7d97c5SJed Brown         }
40820c7d97c5SJed Brown       }
40830c7d97c5SJed Brown 
408453cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
40850c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
40860c7d97c5SJed Brown       my_faces=0;
40870c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {
40880c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40897cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0) {
40900c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
40910c7d97c5SJed Brown             my_faces++;
40920c7d97c5SJed Brown             break;
40930c7d97c5SJed Brown           }
40940c7d97c5SJed Brown         }
40950c7d97c5SJed Brown       }
40960c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
40970c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
40980c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
40990c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
41000c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
41010c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
41020c7d97c5SJed Brown       }
410353cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
41040c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41050c7d97c5SJed Brown         faces_xadj[0]=0;
41060c7d97c5SJed Brown         faces_displacements[0]=0;
41070c7d97c5SJed Brown         j=0;
41080c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
41090c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
41100c7d97c5SJed Brown           if (number_of_faces[i-1]) {
41110c7d97c5SJed Brown             j++;
41120c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
41130c7d97c5SJed Brown           }
41140c7d97c5SJed Brown         }
41150c7d97c5SJed Brown       }
411653cdbc3dSStefano 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);
41170c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
41180c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
41190c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41203828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
41210c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
41220c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
41230c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
41240c7d97c5SJed Brown       }
41250c7d97c5SJed Brown 
41260c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41273828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
41280c7d97c5SJed Brown         ncon=1;
41290c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
41300c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
41310c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
41320c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
41330c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
41340c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
41350c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
41364fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
41373828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
41383828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
41393828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
41400c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
4141142dfd88SStefano 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);
41423828260eSStefano Zampini           } else {
41433828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
4144142dfd88SStefano 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);
41453828260eSStefano Zampini           }
41464fad6a16SStefano Zampini         } else {
41474fad6a16SStefano Zampini           for (i=0;i<n_subdomains;i++) {
41484fad6a16SStefano Zampini             metis_coarse_subdivision[i]=i;
41494fad6a16SStefano Zampini           }
41504fad6a16SStefano Zampini         }
41510c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
41520c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
41530bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
41540c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
41550bdf917eSStefano Zampini         for (i=0;i<size_prec_comm;i++) { coarse_subdivision[i]=MPI_PROC_NULL; }
41560bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++)   { coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]); }
41570c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
41580c7d97c5SJed Brown       }
41590c7d97c5SJed Brown 
41600c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
41610c7d97c5SJed Brown       if (!(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts) {
4162da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
4163da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
41640c7d97c5SJed Brown       }
4165da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
4166da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
416753cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
41680c7d97c5SJed Brown 
41690c7d97c5SJed Brown       if (coarse_color == 0) {
417053cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
417153cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
41720c7d97c5SJed Brown       } else {
41730c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
41740c7d97c5SJed Brown       }
41750c7d97c5SJed Brown 
41767cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
41770c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
41780c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
41790bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
41800bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
41810c7d97c5SJed Brown         /* some initializations */
41820c7d97c5SJed Brown         displacements_recv[0]=0;
41830bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
41840c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
41850bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
41860bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
41870bdf917eSStefano Zampini             if (coarse_subdivision[i]==j) {
41880c7d97c5SJed Brown               total_count_recv[j]++;
41890bdf917eSStefano Zampini             }
41900bdf917eSStefano Zampini           }
41910bdf917eSStefano Zampini         }
41920c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
41930bdf917eSStefano Zampini         for (i=1;i<size_coarse_comm;i++) { displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1]; }
41940c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
41950c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
41960c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
41973828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
41980c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
41990c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
42003828260eSStefano Zampini               total_count_recv[j]+=1;
42010c7d97c5SJed Brown             }
42020c7d97c5SJed Brown           }
42030c7d97c5SJed Brown         }
4204da1bb401SStefano Zampini         /* for (j=0;j<size_coarse_comm;j++) {
42053828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
42063828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
42073828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
42083828260eSStefano Zampini           }
42093828260eSStefano Zampini           printf("\n");
4210da1bb401SStefano Zampini         } */
42110c7d97c5SJed Brown 
42120c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
42130bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
42140bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
42150bdf917eSStefano Zampini         }
4216da1bb401SStefano Zampini         /* printf("coarse_subdivision in old end new ranks\n");
42170c7d97c5SJed Brown         for (i=0;i<size_prec_comm;i++)
42183828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
42193828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
42203828260eSStefano Zampini           } else {
42213828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
42223828260eSStefano Zampini           }
4223da1bb401SStefano Zampini         printf("\n"); */
42240c7d97c5SJed Brown       }
42250c7d97c5SJed Brown 
42260c7d97c5SJed Brown       /* Scatter new decomposition for send details */
422753cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
42280c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
42290c7d97c5SJed Brown       if (coarse_color == 0) {
423053cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
42310c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
423253cdbc3dSStefano 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);
42330c7d97c5SJed Brown       }
42340c7d97c5SJed Brown 
4235da1bb401SStefano Zampini       /* printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
4236da1bb401SStefano Zampini       if (coarse_color == 0) {
4237da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
4238da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
4239da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
4240da1bb401SStefano Zampini         printf("\n");
4241da1bb401SStefano Zampini       } */
42420c7d97c5SJed Brown 
42430c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
42440bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
4245da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
42460bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
42470c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
42480c7d97c5SJed Brown       }
42490c7d97c5SJed Brown       break;
42500c7d97c5SJed Brown     }
42510c7d97c5SJed Brown 
42520c7d97c5SJed Brown     case(REPLICATED_BDDC):
42530c7d97c5SJed Brown 
42540c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
42550c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
42560c7d97c5SJed Brown       coarse_pc_type  = PCLU;
425753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42580c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
42590c7d97c5SJed Brown       active_rank = rank_prec_comm;
42600c7d97c5SJed Brown       break;
42610c7d97c5SJed Brown 
42620c7d97c5SJed Brown     case(PARALLEL_BDDC):
42630c7d97c5SJed Brown 
42640c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
42650c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
42660c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
426753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42680c7d97c5SJed Brown       coarse_comm = prec_comm;
42690c7d97c5SJed Brown       active_rank = rank_prec_comm;
42700c7d97c5SJed Brown       break;
42710c7d97c5SJed Brown 
42720c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
42730c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
42740c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
42750c7d97c5SJed Brown       coarse_pc_type = PCLU;
427653cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42770c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
42780c7d97c5SJed Brown       active_rank = master_proc;
42790c7d97c5SJed Brown       break;
42800c7d97c5SJed Brown   }
42810c7d97c5SJed Brown 
42820c7d97c5SJed Brown   switch (pcbddc->coarse_communications_type) {
42830c7d97c5SJed Brown 
42840c7d97c5SJed Brown     case(SCATTERS_BDDC):
42850c7d97c5SJed Brown       {
42860c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
42870c7d97c5SJed Brown 
42882e8d2280SStefano Zampini           IS coarse_IS;
42892e8d2280SStefano Zampini 
4290523858cfSStefano Zampini           if (pcbddc->coarsening_ratio == 1) {
4291523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
4292523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
4293523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
4294523858cfSStefano Zampini             /* nonzeros */
4295523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
4296523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
4297523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
4298523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
4299523858cfSStefano Zampini             }
4300523858cfSStefano Zampini           } else {
43010c7d97c5SJed Brown             PetscMPIInt send_size;
4302ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
43030c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
43040c7d97c5SJed Brown             PetscInt    ii,jj;
43050c7d97c5SJed Brown             MPI_Request *requests;
4306ef028eecSStefano Zampini 
4307523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
4308523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
4309523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
4310523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
4311523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
4312523858cfSStefano Zampini             j = 0;
4313523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4314523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
4315523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
4316523858cfSStefano Zampini             }
4317523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
4318523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
43190c7d97c5SJed Brown             /* allocate auxiliary space */
4320523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
43210c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
43220c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
43230c7d97c5SJed Brown             /* allocate stuffs for message massing */
43240c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
4325523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
4326523858cfSStefano Zampini             /* send indices to be inserted */
4327523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4328523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
4329523858cfSStefano 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);
4330523858cfSStefano Zampini             }
4331523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4332523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
4333ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
4334ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
4335ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
4336ef028eecSStefano Zampini               }
4337ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
4338523858cfSStefano Zampini             }
4339523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4340ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4341ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
4342ef028eecSStefano Zampini             }
43430c7d97c5SJed Brown             j = 0;
43440c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
43452e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
43462e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
43470c7d97c5SJed Brown               localdispl2[i] = j;
43480c7d97c5SJed Brown               j += localsizes2[i];
4349523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
43504fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
43512e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
43524fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
43530c7d97c5SJed Brown               }
43544fad6a16SStefano Zampini             }
4355523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
43560c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
43570c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
43580c7d97c5SJed Brown             ins_local_primal_size = 0;
4359ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
4360ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
43610c7d97c5SJed Brown                 ins_local_primal_size++;
4362ea7e1babSStefano Zampini               }
4363ea7e1babSStefano Zampini             }
43640c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
43650c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
43660c7d97c5SJed Brown             j = 0;
4367ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
4368ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
43692e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
43702e8d2280SStefano Zampini                 j++;
4371ea7e1babSStefano Zampini               }
4372ea7e1babSStefano Zampini             }
4373523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
4374523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4375523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
4376523858cfSStefano Zampini             }
4377523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4378523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
4379523858cfSStefano 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);
4380523858cfSStefano Zampini             }
4381523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4382523858cfSStefano Zampini             /* nonzeros */
4383523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
4384523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
43850c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
43860c7d97c5SJed Brown             j=0;
43870c7d97c5SJed Brown             for (i=0;i<pcbddc->coarse_size;i++) {
43880c7d97c5SJed Brown               if (aux_ins_indices[i]==0) {
43890c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
43900c7d97c5SJed Brown               } else {
43910c7d97c5SJed Brown                 aux_ins_indices[i]=j;
43920c7d97c5SJed Brown                 j++;
43930c7d97c5SJed Brown               }
43940c7d97c5SJed Brown             }
43954fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
4396523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
4397523858cfSStefano Zampini               for (k=0;k<j;k++) {
4398523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
43990c7d97c5SJed Brown               }
44000c7d97c5SJed Brown             }
4401523858cfSStefano Zampini             /* check */
4402523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
4403523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
4404523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
44050c7d97c5SJed Brown               }
44060c7d97c5SJed Brown             }
44070c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
44080c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
44090c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
44104fad6a16SStefano Zampini           }
44110c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
4412142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
44130c7d97c5SJed Brown           coarse_comm = prec_comm;
44140c7d97c5SJed Brown           active_rank = rank_prec_comm;
44150c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
44160c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
44170c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
44182e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
44190c7d97c5SJed Brown           /* arrays for values insertion */
44200c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
44212e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
44220c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
44230c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++) {
44240c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
44254fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
44264fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
44274fad6a16SStefano Zampini             }
44280c7d97c5SJed Brown           }
44290c7d97c5SJed Brown         }
44300c7d97c5SJed Brown         break;
44310c7d97c5SJed Brown 
44320c7d97c5SJed Brown     }
44330c7d97c5SJed Brown 
44340c7d97c5SJed Brown     case(GATHERS_BDDC):
44350c7d97c5SJed Brown       {
44360c7d97c5SJed Brown 
44370c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
4438ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
44390c7d97c5SJed Brown 
44400c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
44410c7d97c5SJed Brown           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
44420bdf917eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
44430c7d97c5SJed Brown           ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
44440c7d97c5SJed Brown           ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
44450c7d97c5SJed Brown           /* arrays for values insertion */
44464fad6a16SStefano Zampini           for (i=0;i<size_prec_comm;i++) { localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i]; }
44470c7d97c5SJed Brown           localdispl2[0]=0;
44484fad6a16SStefano Zampini           for (i=1;i<size_prec_comm;i++) { localdispl2[i]=localsizes2[i-1]+localdispl2[i-1]; }
44490c7d97c5SJed Brown           j=0;
44504fad6a16SStefano Zampini           for (i=0;i<size_prec_comm;i++) { j+=localsizes2[i]; }
44510c7d97c5SJed Brown           ierr = PetscMalloc (j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
44520c7d97c5SJed Brown         }
44530c7d97c5SJed Brown 
44540c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
44550c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
4456ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
4457ef028eecSStefano Zampini         for (i=0;i<mysize;i++) {
4458ef028eecSStefano Zampini           send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
4459ef028eecSStefano Zampini         }
44600c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC) {
4461ef028eecSStefano 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);
446253cdbc3dSStefano 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);
44630c7d97c5SJed Brown         } else {
4464ef028eecSStefano 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);
446553cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
44660c7d97c5SJed Brown         }
4467ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
44680c7d97c5SJed Brown         break;
4469da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
44700c7d97c5SJed Brown   }
44710c7d97c5SJed Brown 
44720c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
44730c7d97c5SJed Brown   if (rank_prec_comm == active_rank) {
4474142dfd88SStefano Zampini 
4475142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
4476142dfd88SStefano Zampini 
44770c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
44780c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
44790c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
44800c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
44813b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
4482da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
44833b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
44840c7d97c5SJed Brown     } else {
44854fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
44863b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
44870c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
44883b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
4489da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
4490a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
44910c7d97c5SJed Brown     }
4492142dfd88SStefano Zampini     /* preallocation */
4493142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
4494ef028eecSStefano Zampini 
4495142dfd88SStefano Zampini       PetscInt lrows,lcols;
4496ef028eecSStefano Zampini 
4497142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
4498142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
4499ef028eecSStefano Zampini 
4500142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
4501ef028eecSStefano Zampini 
4502ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
4503ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
4504ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
4505ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
4506ef028eecSStefano Zampini 
4507ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
4508ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
4509ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
4510ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
4511ef028eecSStefano Zampini 
4512ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
4513ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
4514ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
4515ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
4516ef028eecSStefano Zampini 
4517ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
4518ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
4519142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
4520ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
4521ef028eecSStefano Zampini             row_ownership[j]=i;
4522142dfd88SStefano Zampini           }
4523142dfd88SStefano Zampini         }
4524ef028eecSStefano Zampini 
4525ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
4526ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
4527ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
4528ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
4529ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
4530ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
4531ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1]) {
4532ef028eecSStefano Zampini               my_dnz[i] += 1.0;
4533142dfd88SStefano Zampini             } else {
4534ef028eecSStefano Zampini               my_onz[i] += 1.0;
4535142dfd88SStefano Zampini             }
4536ef028eecSStefano Zampini             if (i != j) {
4537ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
4538ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1]) {
4539ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
4540142dfd88SStefano Zampini               } else {
4541ef028eecSStefano Zampini                 my_onz[j] += 1.0;
4542142dfd88SStefano Zampini               }
4543142dfd88SStefano Zampini             }
4544142dfd88SStefano Zampini           }
4545142dfd88SStefano Zampini         }
4546ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
4547ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
4548a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
4549ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
4550ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
4551a929c220SStefano Zampini         }
4552ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
4553ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
4554ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
4555ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
4556ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
4557ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
4558ef028eecSStefano Zampini         for (i=0;i<j;i++) {
4559ef028eecSStefano Zampini           dnz[i] = (PetscInt)array[i];
4560142dfd88SStefano Zampini         }
4561ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
4562ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
4563ef028eecSStefano Zampini         for (i=0;i<j;i++) {
4564ef028eecSStefano Zampini           onz[i] = (PetscInt)array[i];
4565142dfd88SStefano Zampini         }
4566ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
4567ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
4568ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
4569ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
4570ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
4571ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
4572142dfd88SStefano Zampini       } else {
4573142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++) {
4574142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
4575142dfd88SStefano Zampini           offset2=localdispl2[k];
4576142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
4577ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4578ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4579ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4580ef028eecSStefano Zampini           }
4581142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4582142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
4583142dfd88SStefano Zampini           }
4584ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4585142dfd88SStefano Zampini         }
4586142dfd88SStefano Zampini       }
4587142dfd88SStefano Zampini       /* check */
4588142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
4589142dfd88SStefano Zampini         if (dnz[i]>lcols) {
4590142dfd88SStefano Zampini           dnz[i]=lcols;
4591142dfd88SStefano Zampini         }
4592142dfd88SStefano Zampini         if (onz[i]>pcbddc->coarse_size-lcols) {
4593142dfd88SStefano Zampini           onz[i]=pcbddc->coarse_size-lcols;
4594142dfd88SStefano Zampini         }
4595142dfd88SStefano Zampini       }
4596142dfd88SStefano Zampini       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,PETSC_NULL,dnz);CHKERRQ(ierr);
4597142dfd88SStefano Zampini       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,PETSC_NULL,dnz,PETSC_NULL,onz);CHKERRQ(ierr);
4598142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
4599142dfd88SStefano Zampini     } else {
4600523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
4601523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
4602142dfd88SStefano Zampini     }
4603142dfd88SStefano Zampini     /* insert values */
4604523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
46050c7d97c5SJed 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);
4606523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4607523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
4608523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
4609523858cfSStefano 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);
4610523858cfSStefano Zampini       } else {
4611523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4612523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
4613523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
4614523858cfSStefano Zampini           offset2 = localdispl2[k];
4615523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
4616ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4617ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4618ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4619ef028eecSStefano Zampini           }
4620523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
4621523858cfSStefano 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);
4622ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4623523858cfSStefano Zampini         }
4624523858cfSStefano Zampini       }
4625523858cfSStefano Zampini       ins_local_primal_indices = 0;
4626523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
4627ea7e1babSStefano Zampini     } else {
4628ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++) {
4629ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
4630ea7e1babSStefano Zampini         offset2=localdispl2[k];
4631ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
4632ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4633ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++) {
4634ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4635ef028eecSStefano Zampini         }
4636ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
4637ea7e1babSStefano 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);
4638ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4639ea7e1babSStefano Zampini       }
4640ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
4641ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
4642ea7e1babSStefano Zampini     }
46430c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46440c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4645142dfd88SStefano Zampini     /* symmetry of coarse matrix */
4646142dfd88SStefano Zampini     if (issym) {
4647142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
4648142dfd88SStefano Zampini     }
46490c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
46500bdf917eSStefano Zampini   }
46510bdf917eSStefano Zampini 
46520bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
46530bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
46540bdf917eSStefano Zampini      IS local_IS,global_IS;
46550bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
46560bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
46570bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46580bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
46590bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
46600bdf917eSStefano Zampini   }
46610bdf917eSStefano Zampini 
4662a929c220SStefano Zampini   /* free memory no longer needed */
4663a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
4664a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
4665a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
4666a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
4667a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
4668a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
4669a929c220SStefano Zampini 
46700bdf917eSStefano Zampini   /* Eval coarse null space */
46710bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
46720bdf917eSStefano Zampini     const Vec      *nsp_vecs;
46730bdf917eSStefano Zampini     PetscInt       nsp_size,coarse_nsp_size;
46740bdf917eSStefano Zampini     PetscBool      nsp_has_cnst;
46750bdf917eSStefano Zampini     PetscReal      test_null;
46760bdf917eSStefano Zampini     Vec            *coarse_nsp_vecs;
46770bdf917eSStefano Zampini 
46780bdf917eSStefano Zampini     coarse_nsp_size = 0;
46790bdf917eSStefano Zampini     coarse_nsp_vecs = 0;
46800bdf917eSStefano Zampini     ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr);
46810bdf917eSStefano Zampini     if (rank_prec_comm == active_rank) {
46820bdf917eSStefano Zampini       ierr = PetscMalloc((nsp_size+1)*sizeof(Vec),&coarse_nsp_vecs);CHKERRQ(ierr);
46830bdf917eSStefano Zampini       for (i=0;i<nsp_size+1;i++) {
46840bdf917eSStefano Zampini         ierr = VecDuplicate(pcbddc->coarse_vec,&coarse_nsp_vecs[i]);CHKERRQ(ierr);
46850bdf917eSStefano Zampini       }
46860bdf917eSStefano Zampini     }
46870bdf917eSStefano Zampini     if (nsp_has_cnst) {
46880bdf917eSStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
46890bdf917eSStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
46900bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46910bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46920bdf917eSStefano Zampini       if (rank_prec_comm == active_rank) {
46930bdf917eSStefano Zampini         ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
46940bdf917eSStefano Zampini         ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&test_null);CHKERRQ(ierr);
46950bdf917eSStefano Zampini         if (test_null > 1.0e-12 && pcbddc->dbg_flag) {
46960bdf917eSStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Constant coarse null space error % 1.14e\n",test_null);CHKERRQ(ierr);
46970bdf917eSStefano Zampini         }
46980bdf917eSStefano Zampini         ierr = VecCopy(pcbddc->coarse_vec,coarse_nsp_vecs[coarse_nsp_size]);CHKERRQ(ierr);
46990bdf917eSStefano Zampini         coarse_nsp_size++;
47000bdf917eSStefano Zampini       }
47010bdf917eSStefano Zampini     }
47020bdf917eSStefano Zampini     for (i=0;i<nsp_size;i++)  {
47030bdf917eSStefano Zampini       ierr = VecScatterBegin(matis->ctx,nsp_vecs[i],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47040bdf917eSStefano Zampini       ierr = VecScatterEnd  (matis->ctx,nsp_vecs[i],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47050bdf917eSStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
47060bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47070bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47080bdf917eSStefano Zampini       if (rank_prec_comm == active_rank) {
47090bdf917eSStefano Zampini         ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
47100bdf917eSStefano Zampini         ierr = VecNorm(pcbddc->coarse_rhs,NORM_2,&test_null);CHKERRQ(ierr);
47110bdf917eSStefano Zampini         if (test_null > 1.0e-12 && pcbddc->dbg_flag) {
47120bdf917eSStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Vec %d coarse null space error % 1.14e\n",i,test_null);CHKERRQ(ierr);
47130bdf917eSStefano Zampini         }
47140bdf917eSStefano Zampini         ierr = VecCopy(pcbddc->coarse_vec,coarse_nsp_vecs[coarse_nsp_size]);CHKERRQ(ierr);
47150bdf917eSStefano Zampini         coarse_nsp_size++;
47160bdf917eSStefano Zampini       }
47170bdf917eSStefano Zampini     }
47180bdf917eSStefano Zampini     if (coarse_nsp_size > 0) {
47190bdf917eSStefano Zampini       /* TODO orthonormalize vecs */
47200bdf917eSStefano Zampini       ierr = VecNormalize(coarse_nsp_vecs[0],PETSC_NULL);CHKERRQ(ierr);
47210bdf917eSStefano Zampini       ierr = MatNullSpaceCreate(coarse_comm,PETSC_FALSE,coarse_nsp_size,coarse_nsp_vecs,&pcbddc->CoarseNullSpace);CHKERRQ(ierr);
47220bdf917eSStefano Zampini       for (i=0;i<nsp_size+1;i++) {
47230bdf917eSStefano Zampini         ierr = VecDestroy(&coarse_nsp_vecs[i]);CHKERRQ(ierr);
47240bdf917eSStefano Zampini       }
47250bdf917eSStefano Zampini     }
47260bdf917eSStefano Zampini     ierr = PetscFree(coarse_nsp_vecs);CHKERRQ(ierr);
47270bdf917eSStefano Zampini   }
47280bdf917eSStefano Zampini 
47290bdf917eSStefano Zampini   /* KSP for coarse problem */
47300bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
47312e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
47320bdf917eSStefano Zampini 
473353cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
473453cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
473553cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
47363b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
473753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
473853cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
473953cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
47400c7d97c5SJed Brown     /* Allow user's customization */
4741da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
47420c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
474353cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
47444fad6a16SStefano Zampini       i = pcbddc->current_level+1;
47454fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
47464fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
47474fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
474853cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
47490bdf917eSStefano Zampini       if (pcbddc->CoarseNullSpace) { ierr = PCBDDCSetNullSpace(pc_temp,pcbddc->CoarseNullSpace);CHKERRQ(ierr); }
47504fad6a16SStefano Zampini       if (dbg_flag) {
47514fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
47524fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
475353cdbc3dSStefano Zampini       }
47544fad6a16SStefano Zampini     }
47554fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
475653cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4757142dfd88SStefano Zampini 
47582e8d2280SStefano Zampini     ierr = KSPGetTolerances(pcbddc->coarse_ksp,PETSC_NULL,PETSC_NULL,PETSC_NULL,&j);CHKERRQ(ierr);
47592e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
47602e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
47612e8d2280SStefano Zampini     if (j == 1) {
47622e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
47632e8d2280SStefano Zampini       if (isbddc) {
47642e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
47655619798eSStefano Zampini       }
47665619798eSStefano Zampini     }
47670c7d97c5SJed Brown   }
4768a929c220SStefano Zampini   /* Check coarse problem if requested */
4769142dfd88SStefano Zampini   if (dbg_flag && rank_prec_comm == active_rank) {
4770142dfd88SStefano Zampini     KSP       check_ksp;
4771142dfd88SStefano Zampini     PC        check_pc;
4772142dfd88SStefano Zampini     Vec       check_vec;
4773142dfd88SStefano Zampini     PetscReal abs_infty_error,infty_error,lambda_min,lambda_max;
477419fd82e9SBarry Smith     KSPType   check_ksp_type;
47750c7d97c5SJed Brown 
4776142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
4777142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
4778142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
47790bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
4780142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4781142dfd88SStefano Zampini       if (issym) {
4782142dfd88SStefano Zampini         check_ksp_type = KSPCG;
4783142dfd88SStefano Zampini       } else {
4784142dfd88SStefano Zampini         check_ksp_type = KSPGMRES;
4785142dfd88SStefano Zampini       }
4786142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
4787142dfd88SStefano Zampini     } else {
4788142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
4789142dfd88SStefano Zampini     }
4790142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
4791142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4792142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4793142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4794142dfd88SStefano Zampini     /* create random vec */
4795142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
4796142dfd88SStefano Zampini     ierr = VecSetRandom(check_vec,PETSC_NULL);CHKERRQ(ierr);
47970bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) { ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,check_vec,PETSC_NULL);CHKERRQ(ierr); }
4798142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
4799142dfd88SStefano Zampini     /* solve coarse problem */
4800142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
48010bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) { ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,pcbddc->coarse_vec,PETSC_NULL);CHKERRQ(ierr); }
4802142dfd88SStefano Zampini     /* check coarse problem residual error */
4803142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
4804142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4805142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
4806142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4807142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
4808142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
4809142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4810142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
4811142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
4812142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
4813e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
48143b03a366Sstefano_zampini     }
4815142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
4816142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
4817142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
481853cdbc3dSStefano Zampini   }
4819142dfd88SStefano Zampini   if (dbg_flag) { ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); }
48200c7d97c5SJed Brown 
48210c7d97c5SJed Brown   PetscFunctionReturn(0);
48220c7d97c5SJed Brown }
48230c7d97c5SJed Brown 
48240c7d97c5SJed Brown #undef __FUNCT__
48250c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
482653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
48270c7d97c5SJed Brown {
48280c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
48290c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)pc->data;
48300c7d97c5SJed Brown   Mat_IS         *matis  = (Mat_IS*)pc->pmat->data;
4831da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
48327cf533a6SStefano Zampini   PetscInt       *is_indices,*auxis;
48333b03a366Sstefano_zampini   PetscInt       bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
4834da1bb401SStefano Zampini   PetscInt       total_counts,nodes_touched,where_values=1,vertex_size;
4835534831adSStefano Zampini   PetscMPIInt    adapt_interface=0,adapt_interface_reduced=0,NEUMANNCNT=0;
4836da1bb401SStefano Zampini   PetscBool      same_set;
4837a0ba757dSStefano Zampini   MPI_Comm       interface_comm=((PetscObject)pc)->comm;
48383b03a366Sstefano_zampini   PetscBool      use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
48393b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
48403b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
4841a81d60d8SStefano Zampini   IS             used_IS,*custom_ISForDofs;
4842da1bb401SStefano Zampini   PetscScalar    *array;
4843da1bb401SStefano Zampini   PetscScalar    *array2;
4844da1bb401SStefano Zampini   PetscViewer    viewer=pcbddc->dbg_viewer;
4845a929c220SStefano Zampini   PetscInt       *queue_in_global_numbering;
48460c7d97c5SJed Brown 
48470c7d97c5SJed Brown   PetscFunctionBegin;
4848da1bb401SStefano Zampini   /* Setup local adjacency graph */
4849da1bb401SStefano Zampini   mat_graph->nvtxs=pcis->n;
4850534831adSStefano Zampini   if (!mat_graph->xadj) { NEUMANNCNT = 1; }
4851da1bb401SStefano Zampini   ierr = PCBDDCSetupLocalAdjacencyGraph(pc);CHKERRQ(ierr);
4852a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
4853a0ba757dSStefano Zampini   ierr = PetscMalloc4(i,PetscInt,&mat_graph->where,i,PetscInt,&mat_graph->count,i+1,PetscInt,&mat_graph->cptr,i,PetscInt,&mat_graph->queue);CHKERRQ(ierr);
48543972b0daSStefano Zampini   ierr = PetscMalloc2(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched);CHKERRQ(ierr);
4855a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4856a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4857a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4858a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
48593828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
4860a0ba757dSStefano Zampini 
4861a81d60d8SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof
4862a81d60d8SStefano Zampini      Get information about dofs' splitting if provided by the user
4863a81d60d8SStefano Zampini      Otherwise it assumes a constant block size */
4864a81d60d8SStefano Zampini   vertex_size=0;
4865a81d60d8SStefano Zampini   if (!pcbddc->n_ISForDofs) {
4866a81d60d8SStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
4867a81d60d8SStefano Zampini     ierr = PetscMalloc(bs*sizeof(IS),&custom_ISForDofs);CHKERRQ(ierr);
4868a81d60d8SStefano Zampini     for (i=0;i<bs;i++) {
4869a81d60d8SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n/bs,i,bs,&custom_ISForDofs[i]);CHKERRQ(ierr);
4870a81d60d8SStefano Zampini     }
4871a81d60d8SStefano Zampini     ierr = PCBDDCSetDofsSplitting(pc,bs,custom_ISForDofs);CHKERRQ(ierr);
4872a81d60d8SStefano Zampini     vertex_size=1;
4873a81d60d8SStefano Zampini     /* remove my references to IS objects */
4874a81d60d8SStefano Zampini     for (i=0;i<bs;i++) {
4875a81d60d8SStefano Zampini       ierr = ISDestroy(&custom_ISForDofs[i]);CHKERRQ(ierr);
4876a81d60d8SStefano Zampini     }
4877a81d60d8SStefano Zampini     ierr = PetscFree(custom_ISForDofs);CHKERRQ(ierr);
4878a81d60d8SStefano Zampini   }
48799c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
4880a81d60d8SStefano Zampini     ierr = ISGetSize(pcbddc->ISForDofs[i],&k);CHKERRQ(ierr);
48819c0446d6SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
4882a81d60d8SStefano Zampini     for (j=0;j<k;j++) {
48839c0446d6SStefano Zampini       mat_graph->which_dof[is_indices[j]]=i;
48849c0446d6SStefano Zampini     }
48859c0446d6SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
48869c0446d6SStefano Zampini   }
4887a81d60d8SStefano Zampini   /* use mat block size as vertex size if it has not yet set */
4888a81d60d8SStefano Zampini   if (!vertex_size) {
48893b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
48900c7d97c5SJed Brown   }
4891a81d60d8SStefano Zampini 
48923b03a366Sstefano_zampini   /* count number of neigh per node */
48930c7d97c5SJed Brown   total_counts=0;
48943b03a366Sstefano_zampini   for (i=1;i<pcis->n_neigh;i++) {
48950c7d97c5SJed Brown     s=pcis->n_shared[i];
48960c7d97c5SJed Brown     total_counts+=s;
489753cdbc3dSStefano Zampini     for (j=0;j<s;j++) {
48980c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
48990c7d97c5SJed Brown     }
49000c7d97c5SJed Brown   }
4901534831adSStefano Zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for nodes lying on the interface */
490236e030ebSStefano Zampini   ierr = PCBDDCGetNeumannBoundaries(pc,&used_IS);CHKERRQ(ierr);
4903da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4904da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
490536e030ebSStefano Zampini   if (used_IS) {
490636e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&neumann_bsize);CHKERRQ(ierr);
490736e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
490853cdbc3dSStefano Zampini     for (i=0;i<neumann_bsize;i++) {
490953cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
4910534831adSStefano Zampini       if (mat_graph->count[iindex] > NEUMANNCNT && array[iindex]==0.0) {
491153cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
49120c7d97c5SJed Brown         total_counts++;
4913da1bb401SStefano Zampini         array[iindex]=array[iindex]+1.0;
4914f23aa3ddSBarry Smith       } else if (array[iindex]>0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Error for neumann nodes provided to BDDC! They must be uniquely listed! Found duplicate node %d\n",iindex);
49150c7d97c5SJed Brown     }
49160c7d97c5SJed Brown   }
4917da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4918da1bb401SStefano Zampini   /* allocate space for storing the set of neighbours for each node */
4919da1bb401SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&mat_graph->neighbours_set);CHKERRQ(ierr);
4920da1bb401SStefano Zampini   if (mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&mat_graph->neighbours_set[0]);CHKERRQ(ierr); }
4921da1bb401SStefano Zampini   for (i=1;i<mat_graph->nvtxs;i++) mat_graph->neighbours_set[i]=mat_graph->neighbours_set[i-1]+mat_graph->count[i-1];
4922a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
49233b03a366Sstefano_zampini   for (i=1;i<pcis->n_neigh;i++) {
49240c7d97c5SJed Brown     s=pcis->n_shared[i];
49250c7d97c5SJed Brown     for (j=0;j<s;j++) {
49260c7d97c5SJed Brown       k=pcis->shared[i][j];
4927da1bb401SStefano Zampini       mat_graph->neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
49280c7d97c5SJed Brown       mat_graph->count[k]+=1;
49290c7d97c5SJed Brown     }
49300c7d97c5SJed Brown   }
4931da1bb401SStefano Zampini   /* Check consistency of Neumann nodes */
4932da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4933da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4934da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4935da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4936da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4937da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
49383b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
493936e030ebSStefano Zampini   if (used_IS) {
494053cdbc3dSStefano Zampini     for (i=0;i<neumann_bsize;i++) {
494153cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
4942534831adSStefano Zampini       if (mat_graph->count[iindex] > NEUMANNCNT) {
4943da1bb401SStefano Zampini         if (mat_graph->count[iindex]+1 != (PetscInt)array[iindex]) {
4944da1bb401SStefano Zampini           SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Neumann nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,mat_graph->count[iindex]+1,(PetscInt)array[iindex]);
4945da1bb401SStefano Zampini         }
4946da1bb401SStefano Zampini         mat_graph->neighbours_set[iindex][mat_graph->count[iindex]] = -1;
494753cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
49480c7d97c5SJed Brown       }
49490c7d97c5SJed Brown     }
495036e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
49510c7d97c5SJed Brown   }
4952da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4953da1bb401SStefano Zampini   /* sort set of sharing subdomains */
4954da1bb401SStefano Zampini   for (i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],mat_graph->neighbours_set[i]);CHKERRQ(ierr); }
49553b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
4956da1bb401SStefano Zampini   for (i=0;i<mat_graph->nvtxs;i++) {mat_graph->touched[i]=PETSC_FALSE;}
4957da1bb401SStefano Zampini   nodes_touched=0;
495836e030ebSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&used_IS);CHKERRQ(ierr);
4959da1bb401SStefano Zampini   ierr = VecSet(pcis->vec2_N,0.0);CHKERRQ(ierr);
4960da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4961da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4962da1bb401SStefano Zampini   if (used_IS) {
4963da1bb401SStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
4964f23aa3ddSBarry Smith     if (dirichlet_bsize && matis->pure_neumann) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet boundaries are intended to be used with matrices with zeroed rows!\n");
4965da1bb401SStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
4966da1bb401SStefano Zampini     for (i=0;i<dirichlet_bsize;i++) {
4967da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
4968da1bb401SStefano Zampini       if (mat_graph->count[iindex] && !mat_graph->touched[iindex]) {
4969f23aa3ddSBarry Smith         if (array[iindex]>0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"BDDC cannot have nodes which are marked as Neumann and Dirichlet at the same time! Wrong node %d\n",iindex);
4970da1bb401SStefano Zampini         mat_graph->touched[iindex]=PETSC_TRUE;
4971da1bb401SStefano Zampini         mat_graph->where[iindex]=0;
4972da1bb401SStefano Zampini         nodes_touched++;
4973da1bb401SStefano Zampini         array2[iindex]=array2[iindex]+1.0;
4974da1bb401SStefano Zampini       }
4975da1bb401SStefano Zampini     }
4976da1bb401SStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
4977da1bb401SStefano Zampini   }
4978da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4979da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4980da1bb401SStefano Zampini   /* Check consistency of Dirichlet nodes */
4981da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4982da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4983da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4984da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4985da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4986da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4987da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4988da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4989da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4990da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4991da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4992da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4993da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
499436e030ebSStefano Zampini   if (used_IS) {
499536e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
499636e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
49973b03a366Sstefano_zampini     for (i=0;i<dirichlet_bsize;i++) {
4998da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
4999da1bb401SStefano Zampini       if (array[iindex]>1.0 && array[iindex]!=array2[iindex]) {
5000da1bb401SStefano Zampini          SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,(PetscInt)array[iindex],(PetscInt)array2[iindex]);
5001da1bb401SStefano Zampini       }
50023b03a366Sstefano_zampini     }
500336e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
50043b03a366Sstefano_zampini   }
5005da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5006da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5007da1bb401SStefano Zampini 
50080c7d97c5SJed Brown   for (i=0;i<mat_graph->nvtxs;i++) {
50093b03a366Sstefano_zampini     if (!mat_graph->count[i]) {  /* interior nodes */
50100c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
50110c7d97c5SJed Brown       mat_graph->where[i]=0;
50120c7d97c5SJed Brown       nodes_touched++;
50130c7d97c5SJed Brown     }
50140c7d97c5SJed Brown   }
50150c7d97c5SJed Brown   mat_graph->ncmps = 0;
5016da1bb401SStefano Zampini   i=0;
50170c7d97c5SJed Brown   while (nodes_touched<mat_graph->nvtxs) {
5018a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
50190c7d97c5SJed Brown     while (mat_graph->touched[i]) i++;
50200c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
5021a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
50220c7d97c5SJed Brown     nodes_touched++;
5023a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
50240c7d97c5SJed Brown     for (j=i+1;j<mat_graph->nvtxs;j++) {
5025a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
5026da1bb401SStefano Zampini       if (!mat_graph->touched[j] && mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j]) {
5027a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
50280c7d97c5SJed Brown         same_set=PETSC_TRUE;
50290c7d97c5SJed Brown         for (k=0;k<mat_graph->count[j];k++) {
5030da1bb401SStefano Zampini           if (mat_graph->neighbours_set[i][k]!=mat_graph->neighbours_set[j][k]) {
50310c7d97c5SJed Brown             same_set=PETSC_FALSE;
50320c7d97c5SJed Brown           }
50330c7d97c5SJed Brown         }
5034a0ba757dSStefano Zampini         /* I found a friend of mine */
50350c7d97c5SJed Brown         if (same_set) {
5036a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
50370c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
50380c7d97c5SJed Brown           nodes_touched++;
50390c7d97c5SJed Brown         }
50400c7d97c5SJed Brown       }
50410c7d97c5SJed Brown     }
5042a0ba757dSStefano Zampini     where_values++;
50430c7d97c5SJed Brown   }
5044a0ba757dSStefano Zampini   where_values--; if (where_values<0) where_values=0;
5045a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
5046a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
5047a0ba757dSStefano Zampini   if (where_values) {
5048a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
5049a0ba757dSStefano Zampini   }
5050a929c220SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&queue_in_global_numbering);CHKERRQ(ierr);
5051a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
5052a0ba757dSStefano Zampini   for (i=0;i<where_values;i++) {
50537cf533a6SStefano Zampini     /* We are not sure that on a given subset of the local interface,
50547cf533a6SStefano Zampini        two connected components will be the same among sharing subdomains */
50553b03a366Sstefano_zampini     if (mat_graph->where_ncmps[i]>1) {
5056a0ba757dSStefano Zampini       adapt_interface=1;
5057a0ba757dSStefano Zampini       break;
5058a0ba757dSStefano Zampini     }
5059a0ba757dSStefano Zampini   }
5060a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
5061da1bb401SStefano Zampini   if (pcbddc->dbg_flag && adapt_interface_reduced) {
5062d8923723SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Adapting interface\n");CHKERRQ(ierr);
5063da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
5064da1bb401SStefano Zampini   }
5065a0ba757dSStefano Zampini   if (where_values && adapt_interface_reduced) {
5066a0ba757dSStefano Zampini     PetscInt    sum_requests=0,my_rank;
5067a0ba757dSStefano Zampini     PetscInt    buffer_size,start_of_recv,size_of_recv,start_of_send;
5068a0ba757dSStefano Zampini     PetscInt    temp_buffer_size,ins_val,global_where_counter;
5069a0ba757dSStefano Zampini     PetscInt    *cum_recv_counts;
5070a0ba757dSStefano Zampini     PetscInt    *where_to_nodes_indices;
5071a0ba757dSStefano Zampini     PetscInt    *petsc_buffer;
5072a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
5073a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
5074a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
5075a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
5076a0ba757dSStefano Zampini     PetscInt    *sizes_of_sends;
5077a0ba757dSStefano Zampini     MPI_Request *send_requests;
5078a0ba757dSStefano Zampini     MPI_Request *recv_requests;
5079a0ba757dSStefano Zampini     PetscInt    *where_cc_adapt;
5080a0ba757dSStefano Zampini     PetscInt    **temp_buffer;
5081a0ba757dSStefano Zampini     PetscInt    *nodes_to_temp_buffer_indices;
5082a0ba757dSStefano Zampini     PetscInt    *add_to_where;
50837cf533a6SStefano Zampini     PetscInt    *aux_new_xadj,*new_xadj,*new_adjncy;
5084a0ba757dSStefano Zampini 
50857cf533a6SStefano Zampini     /* Retrict adjacency graph using information from connected components */
50867cf533a6SStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&aux_new_xadj);CHKERRQ(ierr);
50877cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
50887cf533a6SStefano Zampini       aux_new_xadj[i]=1;
50897cf533a6SStefano Zampini     }
50907cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
50917cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
50927cf533a6SStefano Zampini       for (j=0;j<k;j++) {
50937cf533a6SStefano Zampini         aux_new_xadj[mat_graph->queue[mat_graph->cptr[i]+j]]=k;
50947cf533a6SStefano Zampini       }
50957cf533a6SStefano Zampini     }
50967cf533a6SStefano Zampini     j = 0;
50977cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
50987cf533a6SStefano Zampini       j += aux_new_xadj[i];
50997cf533a6SStefano Zampini     }
51007cf533a6SStefano Zampini     ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&new_xadj);CHKERRQ(ierr);
51017cf533a6SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&new_adjncy);CHKERRQ(ierr);
51027cf533a6SStefano Zampini     new_xadj[0]=0;
51037cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
51047cf533a6SStefano Zampini       new_xadj[i+1]=new_xadj[i]+aux_new_xadj[i];
51057cf533a6SStefano Zampini       if (aux_new_xadj[i]==1) {
51067cf533a6SStefano Zampini         new_adjncy[new_xadj[i]]=i;
51077cf533a6SStefano Zampini       }
51087cf533a6SStefano Zampini     }
5109354b9337SStefano Zampini     ierr = PetscFree(aux_new_xadj);CHKERRQ(ierr);
51107cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
51117cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
51127cf533a6SStefano Zampini       for (j=0;j<k;j++) {
51137cf533a6SStefano Zampini         ierr = PetscMemcpy(&new_adjncy[new_xadj[mat_graph->queue[mat_graph->cptr[i]+j]]],&mat_graph->queue[mat_graph->cptr[i]],k*sizeof(PetscInt));CHKERRQ(ierr);
51147cf533a6SStefano Zampini       }
51157cf533a6SStefano Zampini     }
51167cf533a6SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,mat_graph->nvtxs,new_xadj,new_adjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
51177cf533a6SStefano Zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
51187cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
51197cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
51207cf533a6SStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,k,&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
51217cf533a6SStefano Zampini       ierr = PetscSortIntWithArray(k,&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
51227cf533a6SStefano Zampini     }
51237cf533a6SStefano Zampini     /* allocate some space */
5124a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
5125a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
5126a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
5127a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
5128a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
5129a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
5130a0ba757dSStefano Zampini     for (i=1;i<where_values+1;i++) {
5131a0ba757dSStefano Zampini       j=0;
5132d8923723SStefano Zampini       while (mat_graph->where[j] != i) { j++; }
5133a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
5134da1bb401SStefano Zampini       if (mat_graph->neighbours_set[j][0]!=-1) { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]; } /* We don't want sends/recvs_to/from_self -> here I don't count myself  */
51353b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
5136a0ba757dSStefano Zampini     }
5137a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
5138a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
5139a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
5140a0ba757dSStefano Zampini     for (i=0;i<cum_recv_counts[where_values];i++) {
5141a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
5142a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
5143a0ba757dSStefano Zampini     }
5144a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
5145a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5146a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
5147da1bb401SStefano Zampini       k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
5148a0ba757dSStefano Zampini       for (;k<mat_graph->count[j];k++) {
5149da1bb401SStefano Zampini         ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
5150da1bb401SStefano Zampini         ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
5151a0ba757dSStefano Zampini         sum_requests++;
5152a0ba757dSStefano Zampini       }
5153a0ba757dSStefano Zampini     }
5154a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5155a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5156a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
5157a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
5158a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
5159a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5160a0ba757dSStefano Zampini       for (j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++) {
51613b03a366Sstefano_zampini         /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
51623b03a366Sstefano_zampini         if (mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1) {
5163a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
5164a0ba757dSStefano Zampini           break;
5165a0ba757dSStefano Zampini         }
5166a0ba757dSStefano Zampini       }
5167a0ba757dSStefano Zampini     }
5168d8923723SStefano Zampini     buffer_size = 0;
5169d8923723SStefano Zampini     for (i=0;i<where_values;i++) {
5170d8923723SStefano Zampini       if (where_cc_adapt[i]) {
5171d8923723SStefano Zampini         for (j=i;j<mat_graph->ncmps;j++) {
5172d8923723SStefano Zampini           if (mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
5173d8923723SStefano Zampini             buffer_size += 1 + mat_graph->cptr[j+1]-mat_graph->cptr[j];
5174d8923723SStefano Zampini           }
5175d8923723SStefano Zampini         }
5176d8923723SStefano Zampini       }
5177d8923723SStefano Zampini     }
5178d8923723SStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
5179a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
5180a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
5181a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
5182a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
5183a0ba757dSStefano Zampini     sum_requests=0;
5184a0ba757dSStefano Zampini     start_of_send=0;
5185a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
5186a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5187a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5188a0ba757dSStefano Zampini         size_of_send=0;
5189a0ba757dSStefano Zampini         for (j=i;j<mat_graph->ncmps;j++) {
5190a0ba757dSStefano Zampini           if (mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
5191a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
5192a0ba757dSStefano Zampini             size_of_send+=1;
5193a0ba757dSStefano Zampini             for (k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
5194a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
5195a0ba757dSStefano Zampini             }
5196a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
5197a0ba757dSStefano Zampini           }
5198a0ba757dSStefano Zampini         }
5199a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
5200da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
520111d8f4c2SStefano Zampini         sizes_of_sends[i]=size_of_send;
5202a0ba757dSStefano Zampini         for (;k<mat_graph->count[j];k++) {
520311d8f4c2SStefano Zampini           ierr = MPI_Isend(&sizes_of_sends[i],1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
5204da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
5205a0ba757dSStefano Zampini           sum_requests++;
5206a0ba757dSStefano Zampini         }
5207a0ba757dSStefano Zampini         start_of_send+=size_of_send;
5208a0ba757dSStefano Zampini       }
5209a0ba757dSStefano Zampini     }
5210a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5211a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5212a0ba757dSStefano Zampini     buffer_size=0;
5213a0ba757dSStefano Zampini     for (k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
5214a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
5215a0ba757dSStefano Zampini     /* now exchange the data */
5216a0ba757dSStefano Zampini     start_of_recv=0;
5217a0ba757dSStefano Zampini     start_of_send=0;
5218a0ba757dSStefano Zampini     sum_requests=0;
5219a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5220a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5221a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
5222a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
5223da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
5224a0ba757dSStefano Zampini         for (;k<mat_graph->count[j];k++) {
5225da1bb401SStefano Zampini           ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
5226a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
5227da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
5228a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
5229a0ba757dSStefano Zampini           sum_requests++;
5230a0ba757dSStefano Zampini         }
5231a0ba757dSStefano Zampini         start_of_send+=size_of_send;
5232a0ba757dSStefano Zampini       }
5233a0ba757dSStefano Zampini     }
5234a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5235a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5236a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
5237a0ba757dSStefano Zampini     for (k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
5238a0ba757dSStefano Zampini     for (j=0;j<buffer_size;) {
5239a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
5240a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
5241a0ba757dSStefano Zampini        j+=k;
5242a0ba757dSStefano Zampini     }
5243a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
5244a0ba757dSStefano Zampini     start_of_recv=0;
5245a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
5246a0ba757dSStefano Zampini     global_where_counter=0;
5247a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5248a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5249a0ba757dSStefano Zampini         temp_buffer_size=0;
5250a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
5251a0ba757dSStefano Zampini         for (j=0;j<mat_graph->nvtxs;j++) {
5252a0ba757dSStefano Zampini           if (mat_graph->where[j]==i+1) {
5253a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
5254a0ba757dSStefano Zampini             temp_buffer_size++;
5255a0ba757dSStefano Zampini           } else {
5256a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
5257a0ba757dSStefano Zampini           }
5258a0ba757dSStefano Zampini         }
5259a0ba757dSStefano Zampini         /* allocate some temporary space */
5260a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
5261a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
5262a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
5263a0ba757dSStefano Zampini         for (j=1;j<temp_buffer_size;j++) {
5264a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
5265a0ba757dSStefano Zampini         }
5266a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
5267a0ba757dSStefano Zampini            temp buffer structure:
5268a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
5269a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
5270a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
5271a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
5272a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
5273a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
5274a0ba757dSStefano Zampini              [ 0, 0, 0;
5275a0ba757dSStefano Zampini                0, 0, 1;
5276a0ba757dSStefano Zampini                1, 1, 2;
5277a0ba757dSStefano Zampini                1, 1, 2;
5278a0ba757dSStefano Zampini                0, 1, 0; ];
5279a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
5280a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
5281a0ba757dSStefano Zampini                                                                                                                                    */
5282a0ba757dSStefano Zampini         for (j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
5283a0ba757dSStefano Zampini           ins_val=0;
5284a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
5285a0ba757dSStefano Zampini           for (buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
5286a0ba757dSStefano Zampini             for (k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
5287a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
5288a0ba757dSStefano Zampini             }
5289a0ba757dSStefano Zampini             buffer_size+=k;
5290a0ba757dSStefano Zampini             ins_val++;
5291a0ba757dSStefano Zampini           }
5292a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
5293a0ba757dSStefano Zampini           sum_requests++;
5294a0ba757dSStefano Zampini         }
5295a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
5296a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
5297a0ba757dSStefano Zampini         for (j=0;j<temp_buffer_size;j++) {
5298a0ba757dSStefano Zampini           if (!add_to_where[j]) { /* found a new cc  */
5299a0ba757dSStefano Zampini             global_where_counter++;
5300a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
5301a0ba757dSStefano Zampini             for (k=j+1;k<temp_buffer_size;k++) { /* check for other nodes in new cc */
5302a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
5303a0ba757dSStefano Zampini               for (s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++) {
5304a0ba757dSStefano Zampini                 if (temp_buffer[j][s]!=temp_buffer[k][s]) {
5305a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
5306a0ba757dSStefano Zampini                   break;
5307a0ba757dSStefano Zampini                 }
5308a0ba757dSStefano Zampini               }
53092e8d2280SStefano Zampini               if (same_set) { add_to_where[k]=global_where_counter; }
5310a0ba757dSStefano Zampini             }
5311a0ba757dSStefano Zampini           }
5312a0ba757dSStefano Zampini         }
5313a0ba757dSStefano Zampini         /* insert new data in where array */
5314a0ba757dSStefano Zampini         temp_buffer_size=0;
5315a0ba757dSStefano Zampini         for (j=0;j<mat_graph->nvtxs;j++) {
5316a0ba757dSStefano Zampini           if (mat_graph->where[j]==i+1) {
5317a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
5318a0ba757dSStefano Zampini             temp_buffer_size++;
5319a0ba757dSStefano Zampini           }
5320a0ba757dSStefano Zampini         }
5321a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
5322a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
5323a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
5324a0ba757dSStefano Zampini       }
5325a0ba757dSStefano Zampini     }
5326a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
5327a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
5328a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
5329a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
5330a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
5331a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
5332a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
5333a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
5334a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
5335a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
533623d4d1a5SStefano Zampini     ierr = PetscFree(where_cc_adapt);CHKERRQ(ierr);
5337a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
5338a0ba757dSStefano Zampini     if (global_where_counter) {
5339a0ba757dSStefano Zampini       for (i=0;i<mat_graph->nvtxs;i++) { mat_graph->touched[i]=PETSC_FALSE; }
5340a0ba757dSStefano Zampini       global_where_counter=0;
5341a0ba757dSStefano Zampini       for (i=0;i<mat_graph->nvtxs;i++) {
5342a0ba757dSStefano Zampini         if (mat_graph->where[i] && !mat_graph->touched[i]) {
5343a0ba757dSStefano Zampini           global_where_counter++;
5344a0ba757dSStefano Zampini           for (j=i+1;j<mat_graph->nvtxs;j++) {
5345a0ba757dSStefano Zampini             if (!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
5346a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
5347a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
5348a0ba757dSStefano Zampini             }
5349a0ba757dSStefano Zampini           }
5350a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
5351a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
5352a0ba757dSStefano Zampini         }
5353a0ba757dSStefano Zampini       }
5354a0ba757dSStefano Zampini       where_values=global_where_counter;
5355a0ba757dSStefano Zampini     }
5356a0ba757dSStefano Zampini     if (global_where_counter) {
5357a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
5358a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
5359a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
5360a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
5361a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
5362a0ba757dSStefano Zampini     }
53633b03a366Sstefano_zampini   } /* Finished adapting interface */
5364a929c220SStefano Zampini   /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
5365a929c220SStefano Zampini   for (i=0;i<mat_graph->ncmps;i++) {
5366a929c220SStefano Zampini     k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
5367a929c220SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,k,&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
5368a929c220SStefano Zampini     ierr = PetscSortIntWithArray(k,&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
5369a929c220SStefano Zampini   }
5370a929c220SStefano Zampini 
53710c7d97c5SJed Brown   PetscInt  nfc=0;
53720c7d97c5SJed Brown   PetscInt  nec=0;
53730c7d97c5SJed Brown   PetscInt  nvc=0;
53743b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
53750c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
53763b03a366Sstefano_zampini     if (mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size) {
5377534831adSStefano Zampini       if (mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1) { /* 1 neigh Neumann fake included */
53780c7d97c5SJed Brown         nfc++;
53793b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
53803b03a366Sstefano_zampini         nec++;
53813b03a366Sstefano_zampini       }
53820c7d97c5SJed Brown     } else {
53833b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
53843b03a366Sstefano_zampini     }
53853b03a366Sstefano_zampini   }
53863b03a366Sstefano_zampini   if (!nec) { /* we are in a 2d case -> no faces, only edges */
53873b03a366Sstefano_zampini     nec = nfc;
53883b03a366Sstefano_zampini     nfc = 0;
53893b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
53903b03a366Sstefano_zampini   }
53913972b0daSStefano Zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set. */
53923972b0daSStefano Zampini   k=0;
53933972b0daSStefano Zampini   for (i=0; i<mat_graph->ncmps; i++) {
53943972b0daSStefano Zampini     j=mat_graph->cptr[i+1]-mat_graph->cptr[i];
53953972b0daSStefano Zampini     if (j > k) {
53963972b0daSStefano Zampini       k=j;
53973972b0daSStefano Zampini     }
5398ba1573a8SStefano Zampini     if (j<=vertex_size) {
5399ba1573a8SStefano Zampini       k+=vertex_size;
5400ba1573a8SStefano Zampini     }
54013972b0daSStefano Zampini   }
54023972b0daSStefano Zampini   ierr = PetscMalloc(k*sizeof(PetscInt),&auxis);CHKERRQ(ierr);
54033b03a366Sstefano_zampini   if (!pcbddc->vertices_flag && !pcbddc->edges_flag) {
54043b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
54053b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
54063b03a366Sstefano_zampini   }
54073b03a366Sstefano_zampini   if (!pcbddc->vertices_flag && !pcbddc->faces_flag) {
54083b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
54093b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
54103b03a366Sstefano_zampini   }
54113b03a366Sstefano_zampini   nfc=0;
54123b03a366Sstefano_zampini   nec=0;
54133b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
54143b03a366Sstefano_zampini     if (mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size) {
54153b03a366Sstefano_zampini       for (j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
54163972b0daSStefano Zampini         auxis[j]=mat_graph->queue[mat_graph->cptr[i]+j];
54173b03a366Sstefano_zampini       }
54183b03a366Sstefano_zampini       if (mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1) {
54193b03a366Sstefano_zampini         if (twodim_flag) {
54203b03a366Sstefano_zampini           if (use_edges) {
54213972b0daSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
54223b03a366Sstefano_zampini             nec++;
54233b03a366Sstefano_zampini           }
54243b03a366Sstefano_zampini         } else {
54253b03a366Sstefano_zampini           if (use_faces) {
54263972b0daSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
54273b03a366Sstefano_zampini             nfc++;
54283b03a366Sstefano_zampini           }
54293b03a366Sstefano_zampini         }
54303b03a366Sstefano_zampini       } else {
54313b03a366Sstefano_zampini         if (use_edges) {
54323972b0daSStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
54330c7d97c5SJed Brown           nec++;
54340c7d97c5SJed Brown         }
54350c7d97c5SJed Brown       }
54360c7d97c5SJed Brown     }
54373b03a366Sstefano_zampini   }
54383b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
54393b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
54403b03a366Sstefano_zampini   nvc=0;
54410c7d97c5SJed Brown   if (!pcbddc->constraints_flag) {
54423b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
54433b03a366Sstefano_zampini       if (mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size) {
54443b03a366Sstefano_zampini         for (j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
54453972b0daSStefano Zampini           auxis[nvc]=mat_graph->queue[j];
54460c7d97c5SJed Brown           nvc++;
54470c7d97c5SJed Brown         }
54480c7d97c5SJed Brown       }
54490c7d97c5SJed Brown     }
54500c7d97c5SJed Brown   }
5451a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
54523972b0daSStefano Zampini   ierr = PetscSortInt(nvc,auxis);CHKERRQ(ierr);
54533972b0daSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,auxis,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
5454e269702eSStefano Zampini   if (pcbddc->dbg_flag) {
5455d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5456d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5457d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
54580c7d97c5SJed Brown     for (i=0;i<mat_graph->ncmps;i++) {
54593b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
54603b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
5461da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"subdomains: ");
5462da1bb401SStefano Zampini       for (j=0;j<mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]; j++) {
5463da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->neighbours_set[mat_graph->queue[mat_graph->cptr[i]]][j]);
5464da1bb401SStefano Zampini       }
5465da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");
54660c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++) {
5467a929c220SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",mat_graph->queue[j],queue_in_global_numbering[j]);CHKERRQ(ierr);
54680c7d97c5SJed Brown       }
54690c7d97c5SJed Brown     }
5470da1bb401SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
54713b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
54723b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
54733b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
5474d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
54750c7d97c5SJed Brown   }
54763972b0daSStefano Zampini   ierr = PetscFree(auxis);CHKERRQ(ierr);
5477a929c220SStefano Zampini   ierr = PetscFree(queue_in_global_numbering);CHKERRQ(ierr);
54780c7d97c5SJed Brown   PetscFunctionReturn(0);
54790c7d97c5SJed Brown }
54800c7d97c5SJed Brown 
54810c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
54820c7d97c5SJed Brown 
54830c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
5484da1bb401SStefano Zampini    in source file contig.c of METIS library (version 5.0.1)
5485da1bb401SStefano Zampini    It finds connected components of each partition labeled from 1 to n_dist  */
54860c7d97c5SJed Brown 
54870c7d97c5SJed Brown #undef __FUNCT__
54880c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
54899c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist)
54900c7d97c5SJed Brown {
54910c7d97c5SJed Brown   PetscInt  i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
54920c7d97c5SJed Brown   PetscInt  *xadj, *adjncy, *where, *queue;
54930c7d97c5SJed Brown   PetscInt  *cptr;
54940c7d97c5SJed Brown   PetscBool *touched;
54950c7d97c5SJed Brown 
54960c7d97c5SJed Brown   PetscFunctionBegin;
54970c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
54980c7d97c5SJed Brown   xadj    = graph->xadj;
54990c7d97c5SJed Brown   adjncy  = graph->adjncy;
55000c7d97c5SJed Brown   where   = graph->where;
55010c7d97c5SJed Brown   touched = graph->touched;
55020c7d97c5SJed Brown   queue   = graph->queue;
55030c7d97c5SJed Brown   cptr    = graph->cptr;
55040c7d97c5SJed Brown 
55052e8d2280SStefano Zampini   for (i=0; i<nvtxs; i++) {
55060c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
55072e8d2280SStefano Zampini   }
55080c7d97c5SJed Brown 
55090c7d97c5SJed Brown   cum_queue=0;
55100c7d97c5SJed Brown   ncmps=0;
55110c7d97c5SJed Brown 
55120c7d97c5SJed Brown   for (n=0; n<n_dist; n++) {
5513da1bb401SStefano Zampini     pid = n+1;  /* partition labeled by 0 is discarded */
55140c7d97c5SJed Brown     nleft = 0;
55150c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
55160c7d97c5SJed Brown       if (where[i] == pid)
55170c7d97c5SJed Brown         nleft++;
55180c7d97c5SJed Brown     }
55190c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
55200c7d97c5SJed Brown       if (where[i] == pid)
55210c7d97c5SJed Brown         break;
55220c7d97c5SJed Brown     }
55230c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
55240c7d97c5SJed Brown     queue[cum_queue] = i;
55250c7d97c5SJed Brown     first = 0; last = 1;
55260c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
55270c7d97c5SJed Brown     ncmps_pid = 0;
55280c7d97c5SJed Brown     while (first != nleft) {
55290c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
55300c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
55310c7d97c5SJed Brown         ncmps_pid++;
55320c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
55330c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
55340c7d97c5SJed Brown             break;
55350c7d97c5SJed Brown         }
55360c7d97c5SJed Brown         queue[cum_queue+last] = i;
55370c7d97c5SJed Brown         last++;
55380c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
55390c7d97c5SJed Brown       }
55400c7d97c5SJed Brown       i = queue[cum_queue+first];
55410c7d97c5SJed Brown       first++;
55420c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
55430c7d97c5SJed Brown         k = adjncy[j];
55440c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
55450c7d97c5SJed Brown           queue[cum_queue+last] = k;
55460c7d97c5SJed Brown           last++;
55470c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
55480c7d97c5SJed Brown         }
55490c7d97c5SJed Brown       }
55500c7d97c5SJed Brown     }
55510c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
55520c7d97c5SJed Brown     ncmps_pid++;
55530c7d97c5SJed Brown     cum_queue=cptr[ncmps];
5554a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
55550c7d97c5SJed Brown   }
55560c7d97c5SJed Brown   graph->ncmps = ncmps;
55570c7d97c5SJed Brown 
55580c7d97c5SJed Brown   PetscFunctionReturn(0);
55590c7d97c5SJed Brown }
5560